##// END OF EJS Templates
Merge beta branch into stable
marcink -
r2776:63e58ef8 merge default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -0,0 +1,38 b''
1 language: python
2 python:
3 - "2.5"
4 - "2.6"
5 - "2.7"
6
7 env:
8 - TEST_DB=sqlite:////tmp/rhodecode_test.sqlite
9 - TEST_DB=mysql://root@127.0.0.1/rhodecode_test
10 - TEST_DB=postgresql://postgres@127.0.0.1/rhodecode_test
11
12 # command to install dependencies
13 before_script:
14 - mysql -e 'create database rhodecode_test;'
15 - psql -c 'create database rhodecode_test;' -U postgres
16 - git --version
17
18 before_install:
19 - sudo apt-get remove git
20 - sudo add-apt-repository ppa:pdoes/ppa -y
21 - sudo apt-get update -y
22 - sudo apt-get install git -y
23
24 install:
25 - pip install mysql-python psycopg2 mock unittest2
26 - pip install . --use-mirrors
27
28 # command to run tests
29 script: nosetests
30
31 notifications:
32 email:
33 - marcinkuz@gmail.com
34 irc: "irc.freenode.org#rhodecode"
35
36 branches:
37 only:
38 - dev
@@ -0,0 +1,244 b''
1 .. _installation_win:
2
3
4 Step by step Installation for Windows
5 =====================================
6
7
8 RhodeCode step-by-step install Guide for Windows
9
10 Target OS: Windows XP SP3 English (Clean installation)
11 + All Windows Updates until 24-may-2012
12
13 Step1 - Install Visual Studio 2008 Express
14 ------------------------------------------
15
16
17 Optional: You can also install MingW, but VS2008 installation is easier
18
19 Download "Visual C++ 2008 Express Edition with SP1" from:
20 http://www.microsoft.com/visualstudio/en-us/products/2008-editions/express
21 (if not found or relocated, google for "visual studio 2008 express" for
22 updated link)
23
24 You can also download full ISO file for offline installation, just
25 choose "All - Offline Install ISO image file" in the previous page and
26 choose "Visual C++ 2008 Express" when installing.
27
28
29 .. note::
30
31 Silverlight Runtime and SQL Server 2008 Express Edition are not
32 required, you can uncheck them
33
34
35 Step2 - Install Python
36 ----------------------
37
38 Install Python 2.x.y (x >= 5) x86 version (32bit). DO NOT USE A 3.x version.
39 Download Python 2.x.y from:
40 http://www.python.org/download/
41
42 Choose "Windows Installer" (32bit version) not "Windows X86-64
43 Installer". While writing this guide, the latest version was v2.7.3.
44 Remember the specific major and minor version installed, because it will
45 be needed in the next step. In this case, it is "2.7".
46
47
48 Step3 - Install Win32py extensions
49 ----------------------------------
50
51 Download pywin32 from:
52 http://sourceforge.net/projects/pywin32/files/
53
54 - Click on "pywin32" folder
55 - Click on the first folder (in this case, Build 217, maybe newer when you try)
56 - Choose the file ending with ".win32-py2.x.exe" -> x being the minor
57 version of Python you installed (in this case, 7)
58 When writing this guide, the file was:
59 http://sourceforge.net/projects/pywin32/files/pywin32/Build%20217/pywin32-217.win32-py2.7.exe/download
60
61
62 Step4 - Python BIN
63 ------------------
64
65 Add Python BIN folder to the path
66
67 You have to add the Python folder to the path, you can do it manually
68 (editing "PATH" environment variable) or using Windows Support Tools
69 that came preinstalled in Vista/7 and can be installed in Windows XP.
70
71 - Using support tools on WINDOWS XP:
72 If you use Windows XP you can install them using Windows XP CD and
73 navigating to \SUPPORT\TOOLS. There, execute Setup.EXE (not MSI).
74 Afterwards, open a CMD and type::
75
76 SETX PATH "%PATH%;[your-python-path]" -M
77
78 Close CMD (the path variable will be updated then)
79
80 - Using support tools on WINDOWS Vista/7:
81
82 Open a CMD and type::
83
84 SETX PATH "%PATH%;[your-python-path]" /M
85
86 Please substitute [your-python-path] with your Python installation path.
87 Typically: C:\\Python27
88
89
90 Step5 - RhodeCode folder structure
91 ----------------------------------
92
93 Create a RhodeCode folder structure
94
95 This is only a example to install RhodeCode, you can of course change
96 it. However, this guide will follow the proposed structure, so please
97 later adapt the paths if you change them. My recommendation is to use
98 folders with NO SPACES. But you can try if you are brave...
99
100 Create the following folder structure::
101
102 C:\RhodeCode
103 C:\RhodeCode\Bin
104 C:\RhodeCode\Env
105 C:\RhodeCode\Repos
106
107
108 Step6 - Install virtualenv
109 ---------------------------
110
111 Install Virtual Env for Python
112
113 Navigate to: http://www.virtualenv.org/en/latest/index.html#installation
114 Right click on "virtualenv.py" file and choose "Save link as...".
115 Download to C:\\RhodeCode (or whatever you want)
116 (the file is located at
117 https://raw.github.com/pypa/virtualenv/master/virtualenv.py)
118
119 Create a virtual Python environment in C:\\RhodeCode\\Env (or similar). To
120 do so, open a CMD (Python Path should be included in Step3), navigate
121 where you downloaded "virtualenv.py", and write::
122
123 python virtualenv.py C:\RhodeCode\Env
124
125 (--no-site-packages is now the default behaviour of virtualenv, no need
126 to include it)
127
128
129 Step7 - Install RhodeCode
130 -------------------------
131
132 Finally, install RhodeCode
133
134 Close previously opened command prompt/s, and open a Visual Studio 2008
135 Command Prompt (**IMPORTANT!!**). To do so, go to Start Menu, and then open
136 "Microsoft Visual C++ 2008 Express Edition" -> "Visual Studio Tools" ->
137 "Visual Studio 2008 Command Prompt"
138
139 In that CMD (loaded with VS2008 PATHs) type::
140
141 cd C:\RhodeCode\Env\Scripts (or similar)
142 activate
143
144 The prompt will change into "(Env) C:\\RhodeCode\\Env\\Scripts" or similar
145 (depending of your folder structure). Then type::
146
147 pip install rhodecode
148
149 (long step, please wait until fully complete)
150
151 Some warnings will appear, don't worry as they are normal.
152
153
154 Step8 - Configuring RhodeCode
155 -----------------------------
156
157
158 steps taken from http://packages.python.org/RhodeCode/setup.html
159
160 You have to use the same Visual Studio 2008 command prompt as Step7, so
161 if you closed it reopen it following the same commands (including the
162 "activate" one). When ready, just type::
163
164 cd C:\RhodeCode\Bin
165 paster make-config RhodeCode production.ini
166
167 Then, you must edit production.ini to fit your needs (ip address, ip
168 port, mail settings, database, whatever). I recommend using NotePad++
169 (free) or similar text editor, as it handles well the EndOfLine
170 character differences between Unix and Windows
171 (http://notepad-plus-plus.org/)
172
173 For the sake of simplicity lets run it with the default settings. After
174 your edits (if any), in the previous Command Prompt, type::
175
176 paster setup-rhodecode production.ini
177
178 (this time a NEW database will be installed, you must follow a different
179 step to later UPGRADE to a newer RhodeCode version)
180
181 The script will ask you for confirmation about creating a NEW database,
182 answer yes (y)
183 The script will ask you for repository path, answer C:\\RhodeCode\\Repos
184 (or similar)
185 The script will ask you for admin username and password, answer "admin"
186 + "123456" (or whatever you want)
187 The script will ask you for admin mail, answer "admin@xxxx.com" (or
188 whatever you want)
189
190 If you make some mistake and the script does not end, don't worry, start
191 it again.
192
193
194 Step9 - Running RhodeCode
195 -------------------------
196
197
198 In the previous command prompt, being in the C:\\RhodeCode\\Bin folder,
199 just type::
200
201 paster serve production.ini
202
203 Open yout web server, and go to http://127.0.0.1:5000
204
205 It works!! :-)
206
207 Remark:
208 If it does not work first time, just Ctrl-C the CMD process and start it
209 again. Don't forget the "http://" in Internet Explorer
210
211
212
213 What this Guide does not cover:
214
215 - Installing Celery
216 - Running RhodeCode as Windows Service. You can investigate here:
217
218 - http://pypi.python.org/pypi/wsgisvc
219 - http://ryrobes.com/python/running-python-scripts-as-a-windows-service/
220 - http://wiki.pylonshq.com/display/pylonscookbook/How+to+run+Pylons+as+a+Windows+service
221
222 - Using Apache. You can investigate here:
223
224 - https://groups.google.com/group/rhodecode/msg/c433074e813ffdc4
225
226
227 Upgrading
228 =========
229
230 Stop running RhodeCode
231 Open a CommandPrompt like in Step7 (VS2008 path + activate) and type::
232
233 easy_install -U rhodecode
234 cd \RhodeCode\Bin
235
236 { backup your production.ini file now} ::
237
238 paster make-config RhodeCode production.ini
239
240 (check changes and update your production.ini accordingly) ::
241
242 paster upgrade-db production.ini (update database)
243
244 Full steps in http://packages.python.org/RhodeCode/upgrade.html No newline at end of file
@@ -0,0 +1,41 b''
1 .. _locking:
2
3 ===================================
4 RhodeCode repository locking system
5 ===================================
6
7
8 | Repos with **locking function=disabled** is the default, that's how repos work
9 today.
10 | Repos with **locking function=enabled** behaves like follows:
11
12 Repos have a state called `locked` that can be true or false.
13 The hg/git commands `hg/git clone`, `hg/git pull`, and `hg/git push`
14 influence this state:
15
16 - The command `hg/git pull <repo>` will lock that repo (locked=true)
17 if the user has write/admin permissions on this repo
18
19 - The command `hg/git clone <repo>` will lock that repo (locked=true) if the
20 user has write/admin permissions on this repo
21
22
23 RhodeCode will remember the user id who locked the repo
24 only this specific user can unlock the repo (locked=false) by calling
25
26 - `hg/git push <repo>`
27
28 every other command on that repo from this user and
29 every command from any other user will result in http return code 423 (locked)
30
31
32 additionally the http error includes the <user> that locked the repo
33 (e.g. “repository <repo> locked by user <user>”)
34
35
36 So the scenario of use for repos with `locking function` enabled is that
37 every initial clone and every pull gives users (with write permission)
38 the exclusive right to do a push.
39
40
41 Each repo can be manually unlocked by admin from the repo settings menu. No newline at end of file
@@ -0,0 +1,50 b''
1 .. _performance:
2
3 ================================
4 Optimizing RhodeCode Performance
5 ================================
6
7 When serving large amount of big repositories RhodeCode can start
8 performing slower than expected. Because of demanding nature of handling large
9 amount of data from version control systems here are some tips how to get
10 the best performance.
11
12 * RhodeCode will perform better on machines with faster disks (SSD/SAN). It's
13 more important to have faster disk than faster CPU.
14
15 * Slowness on initial page can be easily fixed by grouping repositories, and/or
16 increasing cache size (see below)
17
18
19 Follow these few steps to improve performance of RhodeCode system.
20
21
22 1. Increase cache
23
24 in the .ini file::
25
26 beaker.cache.sql_cache_long.expire=3600 <-- set this to higher number
27
28 This option affects the cache expiration time for main page. Having
29 few hundreds of repositories on main page can sometimes make the system
30 to behave slow when cache expires for all of them. Increasing `expire`
31 option to day (86400) or a week (604800) will improve general response
32 times for the main page. RhodeCode has an intelligent cache expiration
33 system and it will expire cache for repositories that had been changed.
34
35 2. Switch from sqlite to postgres or mysql
36
37 sqlite is a good option when having small load on the system. But due to
38 locking issues with sqlite, it's not recommended to use it for larger
39 setup. Switching to mysql or postgres will result in a immediate
40 performance increase.
41
42 3. Scale RhodeCode horizontally
43
44 - running two or more instances on the same server can speed up things a lot
45 - load balance using round robin or ip hash
46 - you need to handle consistent user session storage by switching to
47 db sessions, client side sessions or sharing session data folder across
48 instances. See http://beaker.readthedocs.org/ docs for details.
49 - remember that each instance needs it's own .ini file and unique
50 `instance_id` set in them No newline at end of file
@@ -0,0 +1,70 b''
1 .. _troubleshooting:
2
3
4 ===============
5 Troubleshooting
6 ===============
7
8 :Q: **Missing static files?**
9 :A: Make sure either to set the `static_files = true` in the .ini file or
10 double check the root path for your http setup. It should point to
11 for example:
12 /home/my-virtual-python/lib/python2.6/site-packages/rhodecode/public
13
14 |
15
16 :Q: **Can't install celery/rabbitmq?**
17 :A: Don't worry RhodeCode works without them too. No extra setup is required.
18 Try out great celery docs for further help.
19
20 |
21
22 :Q: **Long lasting push timeouts?**
23 :A: Make sure you set a longer timeouts in your proxy/fcgi settings, timeouts
24 are caused by https server and not RhodeCode.
25
26 |
27
28 :Q: **Large pushes timeouts?**
29 :A: Make sure you set a proper max_body_size for the http server. Very often
30 Apache, Nginx or other http servers kill the connection due to to large
31 body.
32
33 |
34
35 :Q: **Apache doesn't pass basicAuth on pull/push?**
36 :A: Make sure you added `WSGIPassAuthorization true`.
37
38 |
39
40 :Q: **Git fails on push/pull?**
41 :A: Make sure you're using an wsgi http server that can handle chunked encoding
42 such as `waitress` or `gunicorn`
43
44 |
45
46 :Q: **How i use hooks in RhodeCode?**
47 :A: It's easy if they are python hooks just use advanced link in hooks section
48 in Admin panel, that works only for Mercurial. If you want to use githooks,
49 just install proper one in repository eg. create file in
50 `/gitrepo/hooks/pre-receive`. You can also use RhodeCode-extensions to
51 connect to callback hooks, for both Git and Mercurial.
52
53 |
54
55 :Q: **RhodeCode is slow for me, how can i make it faster?**
56 :A: See the :ref:`performance` section
57
58 For further questions search the `Issues tracker`_, or post a message in the
59 `google group rhodecode`_
60
61 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
62 .. _python: http://www.python.org/
63 .. _mercurial: http://mercurial.selenic.com/
64 .. _celery: http://celeryproject.org/
65 .. _rabbitmq: http://www.rabbitmq.com/
66 .. _python-ldap: http://www.python-ldap.org/
67 .. _mercurial-server: http://www.lshift.net/mercurial-server.html
68 .. _PublishingRepositories: http://mercurial.selenic.com/wiki/PublishingRepositories
69 .. _Issues tracker: https://bitbucket.org/marcinkuzminski/rhodecode/issues
70 .. _google group rhodecode: http://groups.google.com/group/rhodecode No newline at end of file
@@ -0,0 +1,51 b''
1 ; RhodeCode Supervisord
2 ; ##########################
3 ; for help see http://supervisord.org/configuration.html
4 ; ##########################
5
6 [inet_http_server] ; inet (TCP) server disabled by default
7 port=127.0.0.1:9001 ; (ip_address:port specifier, *:port for all iface)
8 ;username=user ; (default is no username (open server))
9 ;password=123 ; (default is no password (open server))
10
11 [supervisord]
12 logfile=/%(here)s/supervisord_rhodecode.log ; (main log file;default $CWD/supervisord.log)
13 logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB)
14 logfile_backups=10 ; (num of main logfile rotation backups;default 10)
15 loglevel=info ; (log level;default info; others: debug,warn,trace)
16 pidfile=/%(here)s/supervisord_rhodecode.pid ; (supervisord pidfile;default supervisord.pid)
17 nodaemon=true ; (start in foreground if true;default false)
18 minfds=1024 ; (min. avail startup file descriptors;default 1024)
19 minprocs=200 ; (min. avail process descriptors;default 200)
20 umask=022 ; (process file creation umask;default 022)
21 user=marcink ; (default is current user, required if root)
22 ;identifier=supervisor ; (supervisord identifier, default is 'supervisor')
23 ;directory=/tmp ; (default is not to cd during start)
24 ;nocleanup=true ; (don't clean up tempfiles at start;default false)
25 ;childlogdir=/tmp ; ('AUTO' child log dir, default $TEMP)
26 environment=HOME=/home/marcink ; (key value pairs to add to environment)
27 ;strip_ansi=false ; (strip ansi escape codes in logs; def. false)
28
29 ; the below section must remain in the config file for RPC
30 ; (supervisorctl/web interface) to work, additional interfaces may be
31 ; added by defining them in separate rpcinterface: sections
32 [rpcinterface:supervisor]
33 supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
34
35 [supervisorctl]
36 serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket
37 ;username=user ; should be same as http_username if set
38 ;password=123 ; should be same as http_password if set
39 ;prompt=mysupervisor ; cmd line prompt (default "supervisor")
40 ;history_file=~/.sc_history ; use readline history if available
41
42
43 ; restart with supervisorctl restart rhodecode:*
44 [program:rhodecode]
45 numprocs = 1
46 numprocs_start = 5000 # possible should match ports
47 directory=/home/marcink/rhodecode-dir
48 command = /home/marcink/v-env/bin/paster serve rc.ini
49 process_name = %(program_name)s_%(process_num)04d
50 redirect_stderr=true
51 stdout_logfile=/%(here)s/rhodecode.log No newline at end of file
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
@@ -0,0 +1,249 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.bin.backup_manager
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 Api CLI client for RhodeCode
7
8 :created_on: Jun 3, 2012
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
12 """
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
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 #
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/>.
25
26 from __future__ import with_statement
27 import os
28 import sys
29 import random
30 import urllib2
31 import pprint
32 import argparse
33
34 try:
35 from rhodecode.lib.ext_json import json
36 except ImportError:
37 try:
38 import simplejson as json
39 except ImportError:
40 import json
41
42
43 CONFIG_NAME = '.rhodecode'
44 FORMAT_PRETTY = 'pretty'
45 FORMAT_JSON = 'json'
46
47
48 class RcConf(object):
49 """
50 RhodeCode config for API
51
52 conf = RcConf()
53 conf['key']
54
55 """
56
57 def __init__(self, config_location=None, autoload=True, autocreate=False,
58 config=None):
59 self._conf_name = CONFIG_NAME if not config_location else config_location
60 self._conf = {}
61 if autocreate:
62 self.make_config(config)
63 if autoload:
64 self._conf = self.load_config()
65
66 def __getitem__(self, key):
67 return self._conf[key]
68
69 def __nonzero__(self):
70 if self._conf:
71 return True
72 return False
73
74 def __eq__(self):
75 return self._conf.__eq__()
76
77 def __repr__(self):
78 return 'RcConf<%s>' % self._conf.__repr__()
79
80 def make_config(self, config):
81 """
82 Saves given config as a JSON dump in the _conf_name location
83
84 :param config:
85 :type config:
86 """
87 update = False
88 if os.path.exists(self._conf_name):
89 update = True
90 with open(self._conf_name, 'wb') as f:
91 json.dump(config, f, indent=4)
92
93 if update:
94 sys.stdout.write('Updated config in %s\n' % self._conf_name)
95 else:
96 sys.stdout.write('Created new config in %s\n' % self._conf_name)
97
98 def update_config(self, new_config):
99 """
100 Reads the JSON config updates it's values with new_config and
101 saves it back as JSON dump
102
103 :param new_config:
104 """
105 config = {}
106 try:
107 with open(self._conf_name, 'rb') as conf:
108 config = json.load(conf)
109 except IOError, e:
110 sys.stderr.write(str(e) + '\n')
111
112 config.update(new_config)
113 self.make_config(config)
114
115 def load_config(self):
116 """
117 Loads config from file and returns loaded JSON object
118 """
119 try:
120 with open(self._conf_name, 'rb') as conf:
121 return json.load(conf)
122 except IOError, e:
123 #sys.stderr.write(str(e) + '\n')
124 pass
125
126
127 def api_call(apikey, apihost, format, method=None, **kw):
128 """
129 Api_call wrapper for RhodeCode
130
131 :param apikey:
132 :param apihost:
133 :param format: formatting, pretty means prints and pprint of json
134 json returns unparsed json
135 :param method:
136 """
137 def _build_data(random_id):
138 """
139 Builds API data with given random ID
140
141 :param random_id:
142 :type random_id:
143 """
144 return {
145 "id": random_id,
146 "api_key": apikey,
147 "method": method,
148 "args": kw
149 }
150
151 if not method:
152 raise Exception('please specify method name !')
153 id_ = random.randrange(1, 9999)
154 req = urllib2.Request('%s/_admin/api' % apihost,
155 data=json.dumps(_build_data(id_)),
156 headers={'content-type': 'text/plain'})
157 if format == FORMAT_PRETTY:
158 sys.stdout.write('calling %s to %s \n' % (req.get_data(), apihost))
159 ret = urllib2.urlopen(req)
160 raw_json = ret.read()
161 json_data = json.loads(raw_json)
162 id_ret = json_data['id']
163 _formatted_json = pprint.pformat(json_data)
164 if id_ret == id_:
165 if format == FORMAT_JSON:
166 sys.stdout.write(str(raw_json))
167 else:
168 sys.stdout.write('rhodecode returned:\n%s\n' % (_formatted_json))
169
170 else:
171 raise Exception('something went wrong. '
172 'ID mismatch got %s, expected %s | %s' % (
173 id_ret, id_, _formatted_json))
174
175
176 def argparser(argv):
177 usage = (
178 "rhodecode_api [-h] [--format=FORMAT] [--apikey=APIKEY] [--apihost=APIHOST] "
179 " [--config=CONFIG] "
180 "_create_config or METHOD <key:val> <key2:val> ..."
181 )
182
183 parser = argparse.ArgumentParser(description='RhodeCode API cli',
184 usage=usage)
185
186 ## config
187 group = parser.add_argument_group('config')
188 group.add_argument('--apikey', help='api access key')
189 group.add_argument('--apihost', help='api host')
190 group.add_argument('--config', help='config file')
191
192 group = parser.add_argument_group('API')
193 group.add_argument('method', metavar='METHOD', type=str,
194 help='API method name to call followed by key:value attributes',
195 )
196 group.add_argument('--format', dest='format', type=str,
197 help='output format default: `pretty` can '
198 'be also `%s`' % FORMAT_JSON,
199 default=FORMAT_PRETTY
200 )
201 args, other = parser.parse_known_args()
202 return parser, args, other
203
204
205 def main(argv=None):
206 """
207 Main execution function for cli
208
209 :param argv:
210 :type argv:
211 """
212 if argv is None:
213 argv = sys.argv
214
215 conf = None
216 parser, args, other = argparser(argv)
217
218 api_credentials_given = (args.apikey and args.apihost)
219 if args.method == '_create_config':
220 if not api_credentials_given:
221 raise parser.error('_create_config requires --apikey and --apihost')
222 conf = RcConf(config_location=args.config,
223 autocreate=True, config={'apikey': args.apikey,
224 'apihost': args.apihost})
225
226 if not conf:
227 conf = RcConf(config_location=args.config, autoload=True)
228 if not conf:
229 if not api_credentials_given:
230 parser.error('Could not find config file and missing '
231 '--apikey or --apihost in params')
232
233 apikey = args.apikey or conf['apikey']
234 host = args.apihost or conf['apihost']
235 method = args.method
236 if method == '_create_config':
237 sys.exit()
238
239 try:
240 margs = dict(map(lambda s: s.split(':', 1), other))
241 except:
242 sys.stderr.write('Error parsing arguments \n')
243 sys.exit()
244
245 api_call(apikey, host, args.format, method, **margs)
246 return 0
247
248 if __name__ == '__main__':
249 sys.exit(main(sys.argv))
@@ -0,0 +1,31 b''
1 #!/usr/bin/env python
2 import os
3 import sys
4
5 try:
6 import rhodecode
7 RC_HOOK_VER = '_TMPL_'
8 os.environ['RC_HOOK_VER'] = RC_HOOK_VER
9 from rhodecode.lib.hooks import handle_git_post_receive
10 except ImportError:
11 rhodecode = None
12
13
14 def main():
15 if rhodecode is None:
16 # exit with success if we cannot import rhodecode !!
17 # this allows simply push to this repo even without
18 # rhodecode
19 sys.exit(0)
20
21 repo_path = os.path.abspath('.')
22 push_data = sys.stdin.readlines()
23 # os.environ is modified here by a subprocess call that
24 # runs git and later git executes this hook.
25 # Environ get's some additional info from rhodecode system
26 # like IP or username from basic-auth
27 handle_git_post_receive(repo_path, push_data, os.environ)
28 sys.exit(0)
29
30 if __name__ == '__main__':
31 main()
@@ -0,0 +1,31 b''
1 #!/usr/bin/env python
2 import os
3 import sys
4
5 try:
6 import rhodecode
7 RC_HOOK_VER = '_TMPL_'
8 os.environ['RC_HOOK_VER'] = RC_HOOK_VER
9 from rhodecode.lib.hooks import handle_git_pre_receive
10 except ImportError:
11 rhodecode = None
12
13
14 def main():
15 if rhodecode is None:
16 # exit with success if we cannot import rhodecode !!
17 # this allows simply push to this repo even without
18 # rhodecode
19 sys.exit(0)
20
21 repo_path = os.path.abspath('.')
22 push_data = sys.stdin.readlines()
23 # os.environ is modified here by a subprocess call that
24 # runs git and later git executes this hook.
25 # Environ get's some additional info from rhodecode system
26 # like IP or username from basic-auth
27 handle_git_pre_receive(repo_path, push_data, os.environ)
28 sys.exit(0)
29
30 if __name__ == '__main__':
31 main()
@@ -0,0 +1,133 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.controllers.compare
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 compare controller for pylons showoing differences between two
7 repos, branches, bookmarks or tips
8
9 :created_on: May 6, 2012
10 :author: marcink
11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 :license: GPLv3, see COPYING for more details.
13 """
14 # This program is free software: you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation, either version 3 of the License, or
17 # (at your option) any later version.
18 #
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
23 #
24 # You should have received a copy of the GNU General Public License
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 import logging
27 import traceback
28
29 from webob.exc import HTTPNotFound
30 from pylons import request, response, session, tmpl_context as c, url
31 from pylons.controllers.util import abort, redirect
32 from pylons.i18n.translation import _
33
34 from rhodecode.lib.vcs.exceptions import EmptyRepositoryError, RepositoryError
35 from rhodecode.lib import helpers as h
36 from rhodecode.lib.base import BaseRepoController, render
37 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
38 from rhodecode.lib import diffs
39
40 from rhodecode.model.db import Repository
41 from rhodecode.model.pull_request import PullRequestModel
42
43 log = logging.getLogger(__name__)
44
45
46 class CompareController(BaseRepoController):
47
48 @LoginRequired()
49 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
50 'repository.admin')
51 def __before__(self):
52 super(CompareController, self).__before__()
53
54 def __get_cs_or_redirect(self, rev, repo, redirect_after=True):
55 """
56 Safe way to get changeset if error occur it redirects to changeset with
57 proper message
58
59 :param rev: revision to fetch
60 :param repo: repo instance
61 """
62
63 try:
64 type_, rev = rev
65 return repo.scm_instance.get_changeset(rev)
66 except EmptyRepositoryError, e:
67 if not redirect_after:
68 return None
69 h.flash(h.literal(_('There are no changesets yet')),
70 category='warning')
71 redirect(url('summary_home', repo_name=repo.repo_name))
72
73 except RepositoryError, e:
74 log.error(traceback.format_exc())
75 h.flash(str(e), category='warning')
76 redirect(h.url('summary_home', repo_name=repo.repo_name))
77
78 def index(self, org_ref_type, org_ref, other_ref_type, other_ref):
79
80 org_repo = c.rhodecode_db_repo.repo_name
81 org_ref = (org_ref_type, org_ref)
82 other_ref = (other_ref_type, other_ref)
83 other_repo = request.GET.get('repo', org_repo)
84
85 c.swap_url = h.url('compare_url', repo_name=other_repo,
86 org_ref_type=other_ref[0], org_ref=other_ref[1],
87 other_ref_type=org_ref[0], other_ref=org_ref[1],
88 repo=org_repo)
89
90 c.org_repo = org_repo = Repository.get_by_repo_name(org_repo)
91 c.other_repo = other_repo = Repository.get_by_repo_name(other_repo)
92
93 if c.org_repo is None or c.other_repo is None:
94 log.error('Could not found repo %s or %s' % (org_repo, other_repo))
95 raise HTTPNotFound
96
97 if c.org_repo.scm_instance.alias != 'hg':
98 log.error('Review not available for GIT REPOS')
99 raise HTTPNotFound
100
101 self.__get_cs_or_redirect(rev=org_ref, repo=org_repo)
102 self.__get_cs_or_redirect(rev=other_ref, repo=other_repo)
103
104 c.cs_ranges, discovery_data = PullRequestModel().get_compare_data(
105 org_repo, org_ref, other_repo, other_ref
106 )
107
108 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
109 c.cs_ranges])
110 c.target_repo = c.repo_name
111 # defines that we need hidden inputs with changesets
112 c.as_form = request.GET.get('as_form', False)
113 if request.environ.get('HTTP_X_PARTIAL_XHR'):
114 return render('compare/compare_cs.html')
115
116 c.org_ref = org_ref[1]
117 c.other_ref = other_ref[1]
118 # diff needs to have swapped org with other to generate proper diff
119 _diff = diffs.differ(other_repo, other_ref, org_repo, org_ref,
120 discovery_data)
121 diff_processor = diffs.DiffProcessor(_diff, format='gitdiff')
122 _parsed = diff_processor.prepare()
123
124 c.files = []
125 c.changes = {}
126
127 for f in _parsed:
128 fid = h.FID('', f['filename'])
129 c.files.append([fid, f['operation'], f['filename'], f['stats']])
130 diff = diff_processor.as_html(enable_comments=False, diff_lines=[f])
131 c.changes[fid] = [f['operation'], f['filename'], diff]
132
133 return render('compare/compare_diff.html')
@@ -0,0 +1,404 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.controllers.pullrequests
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 pull requests controller for rhodecode for initializing pull requests
7
8 :created_on: May 7, 2012
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
12 """
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
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 #
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/>.
25 import logging
26 import traceback
27 import formencode
28
29 from webob.exc import HTTPNotFound, HTTPForbidden
30 from collections import defaultdict
31 from itertools import groupby
32
33 from pylons import request, response, session, tmpl_context as c, url
34 from pylons.controllers.util import abort, redirect
35 from pylons.i18n.translation import _
36 from pylons.decorators import jsonify
37
38 from rhodecode.lib.compat import json
39 from rhodecode.lib.base import BaseRepoController, render
40 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator,\
41 NotAnonymous
42 from rhodecode.lib import helpers as h
43 from rhodecode.lib import diffs
44 from rhodecode.lib.utils import action_logger
45 from rhodecode.model.db import User, PullRequest, ChangesetStatus,\
46 ChangesetComment
47 from rhodecode.model.pull_request import PullRequestModel
48 from rhodecode.model.meta import Session
49 from rhodecode.model.repo import RepoModel
50 from rhodecode.model.comment import ChangesetCommentsModel
51 from rhodecode.model.changeset_status import ChangesetStatusModel
52 from rhodecode.model.forms import PullRequestForm
53
54 log = logging.getLogger(__name__)
55
56
57 class PullrequestsController(BaseRepoController):
58
59 @LoginRequired()
60 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
61 'repository.admin')
62 def __before__(self):
63 super(PullrequestsController, self).__before__()
64 repo_model = RepoModel()
65 c.users_array = repo_model.get_users_js()
66 c.users_groups_array = repo_model.get_users_groups_js()
67
68 def _get_repo_refs(self, repo):
69 hist_l = []
70
71 branches_group = ([('branch:%s:%s' % (k, v), k) for
72 k, v in repo.branches.iteritems()], _("Branches"))
73 bookmarks_group = ([('book:%s:%s' % (k, v), k) for
74 k, v in repo.bookmarks.iteritems()], _("Bookmarks"))
75 tags_group = ([('tag:%s:%s' % (k, v), k) for
76 k, v in repo.tags.iteritems()], _("Tags"))
77
78 hist_l.append(bookmarks_group)
79 hist_l.append(branches_group)
80 hist_l.append(tags_group)
81
82 return hist_l
83
84 def show_all(self, repo_name):
85 c.pull_requests = PullRequestModel().get_all(repo_name)
86 c.repo_name = repo_name
87 return render('/pullrequests/pullrequest_show_all.html')
88
89 @NotAnonymous()
90 def index(self):
91 org_repo = c.rhodecode_db_repo
92
93 if org_repo.scm_instance.alias != 'hg':
94 log.error('Review not available for GIT REPOS')
95 raise HTTPNotFound
96
97 other_repos_info = {}
98
99 c.org_refs = self._get_repo_refs(c.rhodecode_repo)
100 c.org_repos = []
101 c.other_repos = []
102 c.org_repos.append((org_repo.repo_name, '%s/%s' % (
103 org_repo.user.username, c.repo_name))
104 )
105
106 # add org repo to other so we can open pull request agains itself
107 c.other_repos.extend(c.org_repos)
108
109 c.default_pull_request = org_repo.repo_name
110 c.default_revs = self._get_repo_refs(org_repo.scm_instance)
111 #add orginal repo
112 other_repos_info[org_repo.repo_name] = {
113 'gravatar': h.gravatar_url(org_repo.user.email, 24),
114 'description': org_repo.description,
115 'revs': h.select('other_ref', '', c.default_revs, class_='refs')
116 }
117
118 #gather forks and add to this list
119 for fork in org_repo.forks:
120 c.other_repos.append((fork.repo_name, '%s/%s' % (
121 fork.user.username, fork.repo_name))
122 )
123 other_repos_info[fork.repo_name] = {
124 'gravatar': h.gravatar_url(fork.user.email, 24),
125 'description': fork.description,
126 'revs': h.select('other_ref', '',
127 self._get_repo_refs(fork.scm_instance),
128 class_='refs')
129 }
130 #add parents of this fork also
131 if org_repo.parent:
132 c.default_pull_request = org_repo.parent.repo_name
133 c.other_repos.append((org_repo.parent.repo_name, '%s/%s' % (
134 org_repo.parent.user.username,
135 org_repo.parent.repo_name))
136 )
137 other_repos_info[org_repo.parent.repo_name] = {
138 'gravatar': h.gravatar_url(org_repo.parent.user.email, 24),
139 'description': org_repo.parent.description,
140 'revs': h.select('other_ref', '',
141 self._get_repo_refs(org_repo.parent.scm_instance),
142 class_='refs')
143 }
144
145 c.other_repos_info = json.dumps(other_repos_info)
146 c.review_members = [org_repo.user]
147 return render('/pullrequests/pullrequest.html')
148
149 @NotAnonymous()
150 def create(self, repo_name):
151 try:
152 _form = PullRequestForm()().to_python(request.POST)
153 except formencode.Invalid, errors:
154 log.error(traceback.format_exc())
155 if errors.error_dict.get('revisions'):
156 msg = 'Revisions: %s' % errors.error_dict['revisions']
157 elif errors.error_dict.get('pullrequest_title'):
158 msg = _('Pull request requires a title with min. 3 chars')
159 else:
160 msg = _('error during creation of pull request')
161
162 h.flash(msg, 'error')
163 return redirect(url('pullrequest_home', repo_name=repo_name))
164
165 org_repo = _form['org_repo']
166 org_ref = _form['org_ref']
167 other_repo = _form['other_repo']
168 other_ref = _form['other_ref']
169 revisions = _form['revisions']
170 reviewers = _form['review_members']
171
172 title = _form['pullrequest_title']
173 description = _form['pullrequest_desc']
174
175 try:
176 pull_request = PullRequestModel().create(
177 self.rhodecode_user.user_id, org_repo, org_ref, other_repo,
178 other_ref, revisions, reviewers, title, description
179 )
180 Session().commit()
181 h.flash(_('Successfully opened new pull request'),
182 category='success')
183 except Exception:
184 h.flash(_('Error occurred during sending pull request'),
185 category='error')
186 log.error(traceback.format_exc())
187 return redirect(url('pullrequest_home', repo_name=repo_name))
188
189 return redirect(url('pullrequest_show', repo_name=other_repo,
190 pull_request_id=pull_request.pull_request_id))
191
192 @NotAnonymous()
193 @jsonify
194 def update(self, repo_name, pull_request_id):
195 pull_request = PullRequest.get_or_404(pull_request_id)
196 if pull_request.is_closed():
197 raise HTTPForbidden()
198 #only owner or admin can update it
199 owner = pull_request.author.user_id == c.rhodecode_user.user_id
200 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
201 reviewers_ids = map(int, filter(lambda v: v not in [None, ''],
202 request.POST.get('reviewers_ids', '').split(',')))
203
204 PullRequestModel().update_reviewers(pull_request_id, reviewers_ids)
205 Session.commit()
206 return True
207 raise HTTPForbidden()
208
209 @NotAnonymous()
210 @jsonify
211 def delete(self, repo_name, pull_request_id):
212 pull_request = PullRequest.get_or_404(pull_request_id)
213 #only owner can delete it !
214 if pull_request.author.user_id == c.rhodecode_user.user_id:
215 PullRequestModel().delete(pull_request)
216 Session().commit()
217 h.flash(_('Successfully deleted pull request'),
218 category='success')
219 return redirect(url('admin_settings_my_account'))
220 raise HTTPForbidden()
221
222 def _load_compare_data(self, pull_request, enable_comments=True):
223 """
224 Load context data needed for generating compare diff
225
226 :param pull_request:
227 :type pull_request:
228 """
229
230 org_repo = pull_request.org_repo
231 (org_ref_type,
232 org_ref_name,
233 org_ref_rev) = pull_request.org_ref.split(':')
234
235 other_repo = pull_request.other_repo
236 (other_ref_type,
237 other_ref_name,
238 other_ref_rev) = pull_request.other_ref.split(':')
239
240 # despite opening revisions for bookmarks/branches/tags, we always
241 # convert this to rev to prevent changes after book or branch change
242 org_ref = ('rev', org_ref_rev)
243 other_ref = ('rev', other_ref_rev)
244
245 c.org_repo = org_repo
246 c.other_repo = other_repo
247
248 c.cs_ranges, discovery_data = PullRequestModel().get_compare_data(
249 org_repo, org_ref, other_repo, other_ref
250 )
251
252 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
253 c.cs_ranges])
254 # defines that we need hidden inputs with changesets
255 c.as_form = request.GET.get('as_form', False)
256
257 c.org_ref = org_ref[1]
258 c.other_ref = other_ref[1]
259 # diff needs to have swapped org with other to generate proper diff
260 _diff = diffs.differ(other_repo, other_ref, org_repo, org_ref,
261 discovery_data)
262 diff_processor = diffs.DiffProcessor(_diff, format='gitdiff')
263 _parsed = diff_processor.prepare()
264
265 c.files = []
266 c.changes = {}
267
268 for f in _parsed:
269 fid = h.FID('', f['filename'])
270 c.files.append([fid, f['operation'], f['filename'], f['stats']])
271 diff = diff_processor.as_html(enable_comments=enable_comments,
272 diff_lines=[f])
273 c.changes[fid] = [f['operation'], f['filename'], diff]
274
275 def show(self, repo_name, pull_request_id):
276 repo_model = RepoModel()
277 c.users_array = repo_model.get_users_js()
278 c.users_groups_array = repo_model.get_users_groups_js()
279 c.pull_request = PullRequest.get_or_404(pull_request_id)
280
281 cc_model = ChangesetCommentsModel()
282 cs_model = ChangesetStatusModel()
283 _cs_statuses = cs_model.get_statuses(c.pull_request.org_repo,
284 pull_request=c.pull_request,
285 with_revisions=True)
286
287 cs_statuses = defaultdict(list)
288 for st in _cs_statuses:
289 cs_statuses[st.author.username] += [st]
290
291 c.pull_request_reviewers = []
292 c.pull_request_pending_reviewers = []
293 for o in c.pull_request.reviewers:
294 st = cs_statuses.get(o.user.username, None)
295 if st:
296 sorter = lambda k: k.version
297 st = [(x, list(y)[0])
298 for x, y in (groupby(sorted(st, key=sorter), sorter))]
299 else:
300 c.pull_request_pending_reviewers.append(o.user)
301 c.pull_request_reviewers.append([o.user, st])
302
303 # pull_requests repo_name we opened it against
304 # ie. other_repo must match
305 if repo_name != c.pull_request.other_repo.repo_name:
306 raise HTTPNotFound
307
308 # load compare data into template context
309 enable_comments = not c.pull_request.is_closed()
310 self._load_compare_data(c.pull_request, enable_comments=enable_comments)
311
312 # inline comments
313 c.inline_cnt = 0
314 c.inline_comments = cc_model.get_inline_comments(
315 c.rhodecode_db_repo.repo_id,
316 pull_request=pull_request_id)
317 # count inline comments
318 for __, lines in c.inline_comments:
319 for comments in lines.values():
320 c.inline_cnt += len(comments)
321 # comments
322 c.comments = cc_model.get_comments(c.rhodecode_db_repo.repo_id,
323 pull_request=pull_request_id)
324
325 # changeset(pull-request) status
326 c.current_changeset_status = cs_model.calculate_status(
327 c.pull_request_reviewers
328 )
329 c.changeset_statuses = ChangesetStatus.STATUSES
330 c.target_repo = c.pull_request.org_repo.repo_name
331 return render('/pullrequests/pullrequest_show.html')
332
333 @NotAnonymous()
334 @jsonify
335 def comment(self, repo_name, pull_request_id):
336 pull_request = PullRequest.get_or_404(pull_request_id)
337 if pull_request.is_closed():
338 raise HTTPForbidden()
339
340 status = request.POST.get('changeset_status')
341 change_status = request.POST.get('change_changeset_status')
342
343 comm = ChangesetCommentsModel().create(
344 text=request.POST.get('text'),
345 repo=c.rhodecode_db_repo.repo_id,
346 user=c.rhodecode_user.user_id,
347 pull_request=pull_request_id,
348 f_path=request.POST.get('f_path'),
349 line_no=request.POST.get('line'),
350 status_change=(ChangesetStatus.get_status_lbl(status)
351 if status and change_status else None)
352 )
353
354 # get status if set !
355 if status and change_status:
356 ChangesetStatusModel().set_status(
357 c.rhodecode_db_repo.repo_id,
358 status,
359 c.rhodecode_user.user_id,
360 comm,
361 pull_request=pull_request_id
362 )
363 action_logger(self.rhodecode_user,
364 'user_commented_pull_request:%s' % pull_request_id,
365 c.rhodecode_db_repo, self.ip_addr, self.sa)
366
367 if request.POST.get('save_close'):
368 PullRequestModel().close_pull_request(pull_request_id)
369 action_logger(self.rhodecode_user,
370 'user_closed_pull_request:%s' % pull_request_id,
371 c.rhodecode_db_repo, self.ip_addr, self.sa)
372
373 Session().commit()
374
375 if not request.environ.get('HTTP_X_PARTIAL_XHR'):
376 return redirect(h.url('pullrequest_show', repo_name=repo_name,
377 pull_request_id=pull_request_id))
378
379 data = {
380 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
381 }
382 if comm:
383 c.co = comm
384 data.update(comm.get_dict())
385 data.update({'rendered_text':
386 render('changeset/changeset_comment_block.html')})
387
388 return data
389
390 @NotAnonymous()
391 @jsonify
392 def delete_comment(self, repo_name, comment_id):
393 co = ChangesetComment.get(comment_id)
394 if co.pull_request.is_closed():
395 #don't allow deleting comments on closed pull request
396 raise HTTPForbidden()
397
398 owner = lambda: co.author.user_id == c.rhodecode_user.user_id
399 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
400 ChangesetCommentsModel().delete(comment=co)
401 Session().commit()
402 return True
403 else:
404 raise HTTPForbidden()
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100755
NO CONTENT: new file 100755
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -2,6 +2,7 b' syntax: glob'
2 *.pyc
2 *.pyc
3 *.swp
3 *.swp
4 *.sqlite
4 *.sqlite
5 *.tox
5 *.egg-info
6 *.egg-info
6 *.egg
7 *.egg
7
8
@@ -20,3 +21,4 b' syntax: regexp'
20 ^RhodeCode\.egg-info$
21 ^RhodeCode\.egg-info$
21 ^rc\.ini$
22 ^rc\.ini$
22 ^fabfile.py
23 ^fabfile.py
24 ^\.rhodecode$
@@ -18,4 +18,9 b' List of contributors to RhodeCode projec'
18 Aras Pranckevicius <aras@unity3d.com>
18 Aras Pranckevicius <aras@unity3d.com>
19 Tony Bussieres <t.bussieres@gmail.com>
19 Tony Bussieres <t.bussieres@gmail.com>
20 Erwin Kroon <e.kroon@smartmetersolutions.nl>
20 Erwin Kroon <e.kroon@smartmetersolutions.nl>
21 nansenat16 <nansenat16@null.tw> No newline at end of file
21 nansenat16 <nansenat16@null.tw>
22 Vincent Duvert <vincent@duvert.net>
23 Takumi IINO <trot.thunder@gmail.com>
24 Indra Talip <indra.talip@gmail.com>
25 James Rhodes <jrhodes@redpointsoftware.com.au>
26 Dominik Ruf <dominikruf@gmail.com> No newline at end of file
@@ -72,25 +72,26 b' RhodeCode Features'
72 Each request can be logged and authenticated.
72 Each request can be logged and authenticated.
73 - Runs on threads unlike hgweb. You can make multiple pulls/pushes simultaneous.
73 - Runs on threads unlike hgweb. You can make multiple pulls/pushes simultaneous.
74 Supports http/https and LDAP
74 Supports http/https and LDAP
75 - Full permissions (private/read/write/admin) and authentication per project.
75 - Full permissions (private/read/write/admin) for each repository, additional
76 One account for web interface and mercurial_ push/pull/clone operations.
76 explicit forking and repository permissions.
77 - Have built in users groups for easier permission management
77 - Have built in users groups for easier permission management
78 - Repository groups let you group repos and manage them easier.
78 - Repository groups let you group repos and manage them easier.
79 - Users can fork other users repo. RhodeCode have also compare view to see
79 - Users can fork other users repo. RhodeCode have also compare view to see
80 combined changeset for all changeset made within single push.
80 combined changeset for all changeset made within single push.
81 - Build in commit-api let's you add, edit and commit files right from RhodeCode
81 - Build in commit-api let's you add, edit and commit files right from RhodeCode
82 interface using simple editor or upload form for binaries.
82 interface using simple editor or upload form for binaries.
83 - Powerfull pull-request driven review system with inline commenting, and
84 changeset statuses, notification system.
85 - Importing SVN repositories from remote locations into RhodeCode.
83 - Mako templates let's you customize the look and feel of the application.
86 - Mako templates let's you customize the look and feel of the application.
84 - Beautiful diffs, annotations and source code browsing all colored by pygments.
87 - Beautiful diffs, annotations and source code browsing all colored by pygments.
85 Raw diffs are made in git-diff format, including git_ binary-patches
88 Raw diffs are made in git-diff format, including GIT_ binary-patches
86 - Mercurial_ branch graph and yui-flot powered graphs with zooming and statistics
89 - Mercurial_ branch graph and yui-flot powered graphs with zooming and statistics
87 - Admin interface with user/permission management. Admin activity journal, logs
90 - Admin interface with user/permission management. Admin activity journal, logs
88 pulls, pushes, forks, registrations and other actions made by all users.
91 pulls, pushes, forks, registrations and other actions made by all users.
89 - Server side forks. It is possible to fork a project and modify it freely
92 - Server side forks. It is possible to fork a project and modify it freely
90 without breaking the main repository. You can even write Your own hooks
93 without breaking the main repository. You can even write Your own hooks
91 and install them
94 and install them
92 - code review with notification system, inline commenting, all parsed using
93 rst syntax
94 - rst and markdown README support for repositories
95 - rst and markdown README support for repositories
95 - Full text search powered by Whoosh on the source files, and file names.
96 - Full text search powered by Whoosh on the source files, and file names.
96 Build in indexing daemons, with optional incremental index build
97 Build in indexing daemons, with optional incremental index build
@@ -110,8 +111,9 b' Incoming / Plans'
110 ----------------
111 ----------------
111
112
112 - Finer granular permissions per branch, repo group or subrepo
113 - Finer granular permissions per branch, repo group or subrepo
113 - pull requests and web based merges
114 - Pull requests with web based merges
114 - per line file history
115 - Per line file history
116 - Simple issue tracker
115 - SSH based authentication with server side key management
117 - SSH based authentication with server side key management
116 - Commit based built in wiki system
118 - Commit based built in wiki system
117 - More statistics and graph (global annotation + some more statistics)
119 - More statistics and graph (global annotation + some more statistics)
@@ -131,7 +133,8 b' Listed bellow are various support resour'
131
133
132 .. note::
134 .. note::
133
135
134 Please try to read the documentation before posting any issues
136 Please try to read the documentation before posting any issues, especially
137 the **troubleshooting section**
135
138
136 - Join the `Google group <http://groups.google.com/group/rhodecode>`_ and ask
139 - Join the `Google group <http://groups.google.com/group/rhodecode>`_ and ask
137 any questions.
140 any questions.
@@ -30,22 +30,31 b' pdebug = false'
30
30
31 [server:main]
31 [server:main]
32 ##nr of threads to spawn
32 ##nr of threads to spawn
33 threadpool_workers = 5
33 #threadpool_workers = 5
34
34
35 ##max request before thread respawn
35 ##max request before thread respawn
36 threadpool_max_requests = 10
36 #threadpool_max_requests = 10
37
37
38 ##option to use threads of process
38 ##option to use threads of process
39 use_threadpool = true
39 #use_threadpool = true
40
40
41 use = egg:Paste#http
41 #use = egg:Paste#http
42 use = egg:waitress#main
42 host = 0.0.0.0
43 host = 0.0.0.0
43 port = 5000
44 port = 5000
44
45
46 [filter:proxy-prefix]
47 # prefix middleware for rc
48 use = egg:PasteDeploy#prefix
49 prefix = /<your-prefix>
50
45 [app:main]
51 [app:main]
46 use = egg:rhodecode
52 use = egg:rhodecode
53 #filter-with = proxy-prefix
47 full_stack = true
54 full_stack = true
48 static_files = true
55 static_files = true
56 # Optional Languages
57 # en, fr, ja, pt_BR, zh_CN, zh_TW
49 lang = en
58 lang = en
50 cache_dir = %(here)s/data
59 cache_dir = %(here)s/data
51 index_dir = %(here)s/data/index
60 index_dir = %(here)s/data/index
@@ -54,6 +63,15 b' cut_off_limit = 256000'
54 force_https = false
63 force_https = false
55 commit_parse_limit = 25
64 commit_parse_limit = 25
56 use_gravatar = true
65 use_gravatar = true
66
67 ## alternative_gravatar_url allows you to use your own avatar server application
68 ## the following parts of the URL will be replaced
69 ## {email} user email
70 ## {md5email} md5 hash of the user email (like at gravatar.com)
71 ## {size} size of the image that is expected from the server application
72 #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size}
73 #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size}
74
57 container_auth_enabled = false
75 container_auth_enabled = false
58 proxypass_auth_enabled = false
76 proxypass_auth_enabled = false
59 default_encoding = utf8
77 default_encoding = utf8
@@ -78,7 +96,8 b' default_encoding = utf8'
78 issue_pat = (?:\s*#)(\d+)
96 issue_pat = (?:\s*#)(\d+)
79
97
80 ## server url to the issue, each {id} will be replaced with match
98 ## server url to the issue, each {id} will be replaced with match
81 ## fetched from the regex and {repo} is replaced with repository name
99 ## fetched from the regex and {repo} is replaced with full repository name
100 ## including groups {repo_name} is replaced with just name of repo
82
101
83 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
102 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
84
103
@@ -165,30 +184,34 b' beaker.cache.sql_cache_long.key_length ='
165 ## The storage uses the Container API
184 ## The storage uses the Container API
166 ## that is also used by the cache system.
185 ## that is also used by the cache system.
167
186
168 ## db session example
187 ## db session ##
169
170 #beaker.session.type = ext:database
188 #beaker.session.type = ext:database
171 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
189 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
172 #beaker.session.table_name = db_session
190 #beaker.session.table_name = db_session
173
191
174 ## encrypted cookie session, good for many instances
192 ## encrypted cookie client side session, good for many instances ##
175 #beaker.session.type = cookie
193 #beaker.session.type = cookie
176
194
177 beaker.session.type = file
195 ## file based cookies (default) ##
196 #beaker.session.type = file
197
198
178 beaker.session.key = rhodecode
199 beaker.session.key = rhodecode
179 # secure cookie requires AES python libraries
200 ## secure cookie requires AES python libraries ##
180 #beaker.session.encrypt_key = g654dcno0-9873jhgfreyu
201 #beaker.session.encrypt_key = g654dcno0-9873jhgfreyu
181 #beaker.session.validate_key = 9712sds2212c--zxc123
202 #beaker.session.validate_key = 9712sds2212c--zxc123
182 beaker.session.timeout = 36000
203 ## sets session as invalid if it haven't been accessed for given amount of time
204 beaker.session.timeout = 2592000
183 beaker.session.httponly = true
205 beaker.session.httponly = true
206 #beaker.session.cookie_path = /<your-prefix>
184
207
185 ## uncomment for https secure cookie
208 ## uncomment for https secure cookie ##
186 beaker.session.secure = false
209 beaker.session.secure = false
187
210
188 ##auto save the session to not to use .save()
211 ## auto save the session to not to use .save() ##
189 beaker.session.auto = False
212 beaker.session.auto = False
190
213
191 ##true exire at browser close
214 ## default cookie expiration time in seconds `true` expire at browser close ##
192 #beaker.session.cookie_expires = 3600
215 #beaker.session.cookie_expires = 3600
193
216
194
217
@@ -7,7 +7,7 b' API'
7
7
8 Starting from RhodeCode version 1.2 a simple API was implemented.
8 Starting from RhodeCode version 1.2 a simple API was implemented.
9 There's a single schema for calling all api methods. API is implemented
9 There's a single schema for calling all api methods. API is implemented
10 with JSON protocol both ways. An url to send API request in RhodeCode is
10 with JSON protocol both ways. An url to send API request to RhodeCode is
11 <your_server>/_admin/api
11 <your_server>/_admin/api
12
12
13 API ACCESS FOR WEB VIEWS
13 API ACCESS FOR WEB VIEWS
@@ -59,6 +59,47 b' All responses from API will be `HTTP/1.0'
59 calling api *error* key from response will contain failure description
59 calling api *error* key from response will contain failure description
60 and result will be null.
60 and result will be null.
61
61
62
63 API CLIENT
64 ++++++++++
65
66 From version 1.4 RhodeCode adds a script that allows to easily
67 communicate with API. After installing RhodeCode a `rhodecode-api` script
68 will be available.
69
70 To get started quickly simply run::
71
72 rhodecode-api _create_config --apikey=<youapikey> --apihost=<rhodecode host>
73
74 This will create a file named .config in the directory you executed it storing
75 json config file with credentials. You can skip this step and always provide
76 both of the arguments to be able to communicate with server
77
78
79 after that simply run any api command for example get_repo::
80
81 rhodecode-api get_repo
82
83 calling {"api_key": "<apikey>", "id": 75, "args": {}, "method": "get_repo"} to http://127.0.0.1:5000
84 rhodecode said:
85 {'error': 'Missing non optional `repoid` arg in JSON DATA',
86 'id': 75,
87 'result': None}
88
89 Ups looks like we forgot to add an argument
90
91 Let's try again now giving the repoid as parameters::
92
93 rhodecode-api get_repo repoid:rhodecode
94
95 calling {"api_key": "<apikey>", "id": 39, "args": {"repoid": "rhodecode"}, "method": "get_repo"} to http://127.0.0.1:5000
96 rhodecode said:
97 {'error': None,
98 'id': 39,
99 'result': <json data...>}
100
101
102
62 API METHODS
103 API METHODS
63 +++++++++++
104 +++++++++++
64
105
@@ -76,12 +117,64 b' INPUT::'
76 api_key : "<api_key>"
117 api_key : "<api_key>"
77 method : "pull"
118 method : "pull"
78 args : {
119 args : {
79 "repo_name" : "<reponame>"
120 "repoid" : "<reponame or repo_id>"
121 }
122
123 OUTPUT::
124
125 id : <id_given_in_input>
126 result : "Pulled from `<reponame>`"
127 error : null
128
129
130 rescan_repos
131 ------------
132
133 Dispatch rescan repositories action. If remove_obsolete is set
134 RhodeCode will delete repos that are in database but not in the filesystem.
135 This command can be executed only using api_key belonging to user with admin
136 rights.
137
138 INPUT::
139
140 id : <id_for_response>
141 api_key : "<api_key>"
142 method : "rescan_repos"
143 args : {
144 "remove_obsolete" : "<boolean = Optional(False)>"
80 }
145 }
81
146
82 OUTPUT::
147 OUTPUT::
83
148
84 result : "Pulled from <reponame>"
149 id : <id_given_in_input>
150 result : "{'added': [<list of names of added repos>],
151 'removed': [<list of names of removed repos>]}"
152 error : null
153
154
155 lock
156 ----
157
158 Set locking state on given repository by given user.
159 This command can be executed only using api_key belonging to user with admin
160 rights.
161
162 INPUT::
163
164 id : <id_for_response>
165 api_key : "<api_key>"
166 method : "lock"
167 args : {
168 "repoid" : "<reponame or repo_id>"
169 "userid" : "<user_id or username>",
170 "locked" : "<bool true|false>"
171
172 }
173
174 OUTPUT::
175
176 id : <id_given_in_input>
177 result : "User `<username>` set lock state for repo `<reponame>` to `true|false`"
85 error : null
178 error : null
86
179
87
180
@@ -104,13 +197,15 b' INPUT::'
104
197
105 OUTPUT::
198 OUTPUT::
106
199
200 id : <id_given_in_input>
107 result: None if user does not exist or
201 result: None if user does not exist or
108 {
202 {
109 "id" : "<id>",
203 "user_id" : "<user_id>",
110 "username" : "<username>",
204 "username" : "<username>",
111 "firstname": "<firstname>",
205 "firstname": "<firstname>",
112 "lastname" : "<lastname>",
206 "lastname" : "<lastname>",
113 "email" : "<email>",
207 "email" : "<email>",
208 "emails": "<list_of_all_additional_emails>",
114 "active" : "<bool>",
209 "active" : "<bool>",
115 "admin" :  "<bool>",
210 "admin" :  "<bool>",
116 "ldap_dn" : "<ldap_dn>",
211 "ldap_dn" : "<ldap_dn>",
@@ -143,13 +238,15 b' INPUT::'
143
238
144 OUTPUT::
239 OUTPUT::
145
240
241 id : <id_given_in_input>
146 result: [
242 result: [
147 {
243 {
148 "id" : "<id>",
244 "user_id" : "<user_id>",
149 "username" : "<username>",
245 "username" : "<username>",
150 "firstname": "<firstname>",
246 "firstname": "<firstname>",
151 "lastname" : "<lastname>",
247 "lastname" : "<lastname>",
152 "email" : "<email>",
248 "email" : "<email>",
249 "emails": "<list_of_all_additional_emails>",
153 "active" : "<bool>",
250 "active" : "<bool>",
154 "admin" :  "<bool>",
251 "admin" :  "<bool>",
155 "ldap_dn" : "<ldap_dn>",
252 "ldap_dn" : "<ldap_dn>",
@@ -174,20 +271,32 b' INPUT::'
174 method : "create_user"
271 method : "create_user"
175 args : {
272 args : {
176 "username" : "<username>",
273 "username" : "<username>",
274 "email" : "<useremail>",
177 "password" : "<password>",
275 "password" : "<password>",
178 "email" : "<useremail>",
276 "firstname" : "<firstname> = Optional(None)",
179 "firstname" : "<firstname> = None",
277 "lastname" : "<lastname> = Optional(None)",
180 "lastname" : "<lastname> = None",
278 "active" : "<bool> = Optional(True)",
181 "active" : "<bool> = True",
279 "admin" : "<bool> = Optional(False)",
182 "admin" : "<bool> = False",
280 "ldap_dn" : "<ldap_dn> = Optional(None)"
183 "ldap_dn" : "<ldap_dn> = None"
184 }
281 }
185
282
186 OUTPUT::
283 OUTPUT::
187
284
285 id : <id_given_in_input>
188 result: {
286 result: {
189 "id" : "<new_user_id>",
287 "msg" : "created new user `<username>`",
190 "msg" : "created new user <username>"
288 "user": {
289 "user_id" : "<user_id>",
290 "username" : "<username>",
291 "firstname": "<firstname>",
292 "lastname" : "<lastname>",
293 "email" : "<email>",
294 "emails": "<list_of_all_additional_emails>",
295 "active" : "<bool>",
296 "admin" :  "<bool>",
297 "ldap_dn" : "<ldap_dn>",
298 "last_login": "<last_login>",
299 },
191 }
300 }
192 error: null
301 error: null
193
302
@@ -195,7 +304,7 b' OUTPUT::'
195 update_user
304 update_user
196 -----------
305 -----------
197
306
198 updates current one if such user exists. This command can
307 updates given user if such user exists. This command can
199 be executed only using api_key belonging to user with admin rights.
308 be executed only using api_key belonging to user with admin rights.
200
309
201
310
@@ -206,21 +315,60 b' INPUT::'
206 method : "update_user"
315 method : "update_user"
207 args : {
316 args : {
208 "userid" : "<user_id or username>",
317 "userid" : "<user_id or username>",
209 "username" : "<username>",
318 "username" : "<username> = Optional",
210 "password" : "<password>",
319 "email" : "<useremail> = Optional",
211 "email" : "<useremail>",
320 "password" : "<password> = Optional",
212 "firstname" : "<firstname>",
321 "firstname" : "<firstname> = Optional",
213 "lastname" : "<lastname>",
322 "lastname" : "<lastname> = Optional",
214 "active" : "<bool>",
323 "active" : "<bool> = Optional",
215 "admin" : "<bool>",
324 "admin" : "<bool> = Optional",
216 "ldap_dn" : "<ldap_dn>"
325 "ldap_dn" : "<ldap_dn> = Optional"
217 }
326 }
218
327
219 OUTPUT::
328 OUTPUT::
220
329
330 id : <id_given_in_input>
221 result: {
331 result: {
222 "id" : "<edited_user_id>",
332 "msg" : "updated user ID:<userid> <username>",
223 "msg" : "updated user <username>"
333 "user": {
334 "user_id" : "<user_id>",
335 "username" : "<username>",
336 "firstname": "<firstname>",
337 "lastname" : "<lastname>",
338 "email" : "<email>",
339 "emails": "<list_of_all_additional_emails>",
340 "active" : "<bool>",
341 "admin" :  "<bool>",
342 "ldap_dn" : "<ldap_dn>",
343 "last_login": "<last_login>",
344 },
345 }
346 error: null
347
348
349 delete_user
350 -----------
351
352
353 deletes givenuser if such user exists. This command can
354 be executed only using api_key belonging to user with admin rights.
355
356
357 INPUT::
358
359 id : <id_for_response>
360 api_key : "<api_key>"
361 method : "delete_user"
362 args : {
363 "userid" : "<user_id or username>",
364 }
365
366 OUTPUT::
367
368 id : <id_given_in_input>
369 result: {
370 "msg" : "deleted user ID:<userid> <username>",
371 "user": null
224 }
372 }
225 error: null
373 error: null
226
374
@@ -238,25 +386,29 b' INPUT::'
238 api_key : "<api_key>"
386 api_key : "<api_key>"
239 method : "get_users_group"
387 method : "get_users_group"
240 args : {
388 args : {
241 "group_name" : "<name>"
389 "usersgroupid" : "<users group id or name>"
242 }
390 }
243
391
244 OUTPUT::
392 OUTPUT::
245
393
394 id : <id_given_in_input>
246 result : None if group not exist
395 result : None if group not exist
247 {
396 {
248 "id" : "<id>",
397 "users_group_id" : "<id>",
249 "group_name" : "<groupname>",
398 "group_name" : "<groupname>",
250 "active": "<bool>",
399 "active": "<bool>",
251 "members" : [
400 "members" : [
252 { "id" : "<userid>",
401 {
402 "user_id" : "<user_id>",
253 "username" : "<username>",
403 "username" : "<username>",
254 "firstname": "<firstname>",
404 "firstname": "<firstname>",
255 "lastname" : "<lastname>",
405 "lastname" : "<lastname>",
256 "email" : "<email>",
406 "email" : "<email>",
407 "emails": "<list_of_all_additional_emails>",
257 "active" : "<bool>",
408 "active" : "<bool>",
258 "admin" :  "<bool>",
409 "admin" :  "<bool>",
259 "ldap" : "<ldap_dn>"
410 "ldap_dn" : "<ldap_dn>",
411 "last_login": "<last_login>",
260 },
412 },
261
413
262 ]
414 ]
@@ -280,25 +432,29 b' INPUT::'
280
432
281 OUTPUT::
433 OUTPUT::
282
434
435 id : <id_given_in_input>
283 result : [
436 result : [
284 {
437 {
285 "id" : "<id>",
438 "users_group_id" : "<id>",
286 "group_name" : "<groupname>",
439 "group_name" : "<groupname>",
287 "active": "<bool>",
440 "active": "<bool>",
288 "members" : [
441 "members" : [
289 {
442 {
290 "id" : "<userid>",
443 "user_id" : "<user_id>",
291 "username" : "<username>",
444 "username" : "<username>",
292 "firstname": "<firstname>",
445 "firstname": "<firstname>",
293 "lastname" : "<lastname>",
446 "lastname" : "<lastname>",
294 "email" : "<email>",
447 "email" : "<email>",
295 "active" : "<bool>",
448 "emails": "<list_of_all_additional_emails>",
296 "admin" :  "<bool>",
449 "active" : "<bool>",
297 "ldap" : "<ldap_dn>"
450 "admin" :  "<bool>",
298 },
451 "ldap_dn" : "<ldap_dn>",
299
452 "last_login": "<last_login>",
300 ]
453 },
301 }
454
455 ]
456 },
457
302 ]
458 ]
303 error : null
459 error : null
304
460
@@ -317,14 +473,34 b' INPUT::'
317 method : "create_users_group"
473 method : "create_users_group"
318 args: {
474 args: {
319 "group_name": "<groupname>",
475 "group_name": "<groupname>",
320 "active":"<bool> = True"
476 "active":"<bool> = Optional(True)"
321 }
477 }
322
478
323 OUTPUT::
479 OUTPUT::
324
480
481 id : <id_given_in_input>
325 result: {
482 result: {
326 "id": "<newusersgroupid>",
483 "msg": "created new users group `<groupname>`",
327 "msg": "created new users group <groupname>"
484 "users_group": {
485 "users_group_id" : "<id>",
486 "group_name" : "<groupname>",
487 "active": "<bool>",
488 "members" : [
489 {
490 "user_id" : "<user_id>",
491 "username" : "<username>",
492 "firstname": "<firstname>",
493 "lastname" : "<lastname>",
494 "email" : "<email>",
495 "emails": "<list_of_all_additional_emails>",
496 "active" : "<bool>",
497 "admin" :  "<bool>",
498 "ldap_dn" : "<ldap_dn>",
499 "last_login": "<last_login>",
500 },
501
502 ]
503 },
328 }
504 }
329 error: null
505 error: null
330
506
@@ -343,16 +519,16 b' INPUT::'
343 api_key : "<api_key>"
519 api_key : "<api_key>"
344 method : "add_user_users_group"
520 method : "add_user_users_group"
345 args: {
521 args: {
346 "group_name" : "<groupname>",
522 "usersgroupid" : "<users group id or name>",
347 "username" : "<username>"
523 "userid" : "<user_id or username>",
348 }
524 }
349
525
350 OUTPUT::
526 OUTPUT::
351
527
528 id : <id_given_in_input>
352 result: {
529 result: {
353 "id": "<newusersgroupmemberid>",
354 "success": True|False # depends on if member is in group
530 "success": True|False # depends on if member is in group
355 "msg": "added member <username> to users group <groupname> |
531 "msg": "added member `<username>` to users group `<groupname>` |
356 User is already in that group"
532 User is already in that group"
357 }
533 }
358 error: null
534 error: null
@@ -372,12 +548,13 b' INPUT::'
372 api_key : "<api_key>"
548 api_key : "<api_key>"
373 method : "remove_user_from_users_group"
549 method : "remove_user_from_users_group"
374 args: {
550 args: {
375 "group_name" : "<groupname>",
551 "usersgroupid" : "<users group id or name>",
376 "username" : "<username>"
552 "userid" : "<user_id or username>",
377 }
553 }
378
554
379 OUTPUT::
555 OUTPUT::
380
556
557 id : <id_given_in_input>
381 result: {
558 result: {
382 "success": True|False, # depends on if member is in group
559 "success": True|False, # depends on if member is in group
383 "msg": "removed member <username> from users group <groupname> |
560 "msg": "removed member <username> from users group <groupname> |
@@ -405,23 +582,32 b' INPUT::'
405
582
406 OUTPUT::
583 OUTPUT::
407
584
585 id : <id_given_in_input>
408 result: None if repository does not exist or
586 result: None if repository does not exist or
409 {
587 {
410 "id" : "<id>",
588 "repo_id" : "<repo_id>",
411 "repo_name" : "<reponame>"
589 "repo_name" : "<reponame>"
412 "type" : "<type>",
590 "repo_type" : "<repo_type>",
591 "clone_uri" : "<clone_uri>",
592 "private": : "<bool>",
593 "created_on" : "<datetimecreated>",
413 "description" : "<description>",
594 "description" : "<description>",
595 "landing_rev": "<landing_rev>",
596 "owner": "<repo_owner>",
597 "fork_of": "<name_of_fork_parent>",
414 "members" : [
598 "members" : [
415 {
599 {
416 "type": "user",
600 "type": "user",
417 "id" : "<userid>",
601 "user_id" : "<user_id>",
418 "username" : "<username>",
602 "username" : "<username>",
419 "firstname": "<firstname>",
603 "firstname": "<firstname>",
420 "lastname" : "<lastname>",
604 "lastname" : "<lastname>",
421 "email" : "<email>",
605 "email" : "<email>",
422 "active" : "<bool>",
606 "emails": "<list_of_all_additional_emails>",
423 "admin" :  "<bool>",
607 "active" : "<bool>",
424 "ldap" : "<ldap_dn>",
608 "admin" :  "<bool>",
609 "ldap_dn" : "<ldap_dn>",
610 "last_login": "<last_login>",
425 "permission" : "repository.(read|write|admin)"
611 "permission" : "repository.(read|write|admin)"
426 },
612 },
427
613
@@ -454,12 +640,19 b' INPUT::'
454
640
455 OUTPUT::
641 OUTPUT::
456
642
643 id : <id_given_in_input>
457 result: [
644 result: [
458 {
645 {
459 "id" : "<id>",
646 "repo_id" : "<repo_id>",
460 "repo_name" : "<reponame>"
647 "repo_name" : "<reponame>"
461 "type" : "<type>",
648 "repo_type" : "<repo_type>",
462 "description" : "<description>"
649 "clone_uri" : "<clone_uri>",
650 "private": : "<bool>",
651 "created_on" : "<datetimecreated>",
652 "description" : "<description>",
653 "landing_rev": "<landing_rev>",
654 "owner": "<repo_owner>",
655 "fork_of": "<name_of_fork_parent>",
463 },
656 },
464
657
465 ]
658 ]
@@ -481,14 +674,15 b' INPUT::'
481 api_key : "<api_key>"
674 api_key : "<api_key>"
482 method : "get_repo_nodes"
675 method : "get_repo_nodes"
483 args: {
676 args: {
484 "repo_name" : "<reponame>",
677 "repoid" : "<reponame or repo_id>"
485 "revision" : "<revision>",
678 "revision" : "<revision>",
486 "root_path" : "<root_path>",
679 "root_path" : "<root_path>",
487 "ret_type" : "<ret_type>" = 'all'
680 "ret_type" : "<ret_type> = Optional('all')"
488 }
681 }
489
682
490 OUTPUT::
683 OUTPUT::
491
684
685 id : <id_given_in_input>
492 result: [
686 result: [
493 {
687 {
494 "name" : "<name>"
688 "name" : "<name>"
@@ -516,18 +710,31 b' INPUT::'
516 method : "create_repo"
710 method : "create_repo"
517 args: {
711 args: {
518 "repo_name" : "<reponame>",
712 "repo_name" : "<reponame>",
519 "owner_name" : "<ownername>",
713 "owner" : "<onwer_name_or_id>",
520 "description" : "<description> = ''",
714 "repo_type" : "<repo_type>",
521 "repo_type" : "<type> = 'hg'",
715 "description" : "<description> = Optional('')",
522 "private" : "<bool> = False",
716 "private" : "<bool> = Optional(False)",
523 "clone_uri" : "<clone_uri> = None",
717 "clone_uri" : "<clone_uri> = Optional(None)",
718 "landing_rev" : "<landing_rev> = Optional('tip')",
524 }
719 }
525
720
526 OUTPUT::
721 OUTPUT::
527
722
723 id : <id_given_in_input>
528 result: {
724 result: {
529 "id": "<newrepoid>",
725 "msg": "Created new repository `<reponame>`",
530 "msg": "Created new repository <reponame>",
726 "repo": {
727 "repo_id" : "<repo_id>",
728 "repo_name" : "<reponame>"
729 "repo_type" : "<repo_type>",
730 "clone_uri" : "<clone_uri>",
731 "private": : "<bool>",
732 "created_on" : "<datetimecreated>",
733 "description" : "<description>",
734 "landing_rev": "<landing_rev>",
735 "owner": "<repo_owner>",
736 "fork_of": "<name_of_fork_parent>",
737 },
531 }
738 }
532 error: null
739 error: null
533
740
@@ -545,13 +752,15 b' INPUT::'
545 api_key : "<api_key>"
752 api_key : "<api_key>"
546 method : "delete_repo"
753 method : "delete_repo"
547 args: {
754 args: {
548 "repo_name" : "<reponame>",
755 "repoid" : "<reponame or repo_id>"
549 }
756 }
550
757
551 OUTPUT::
758 OUTPUT::
552
759
760 id : <id_given_in_input>
553 result: {
761 result: {
554 "msg": "Deleted repository <reponame>",
762 "msg": "Deleted repository `<reponame>`",
763 "success": true
555 }
764 }
556 error: null
765 error: null
557
766
@@ -570,15 +779,17 b' INPUT::'
570 api_key : "<api_key>"
779 api_key : "<api_key>"
571 method : "grant_user_permission"
780 method : "grant_user_permission"
572 args: {
781 args: {
573 "repo_name" : "<reponame>",
782 "repoid" : "<reponame or repo_id>"
574 "username" : "<username>",
783 "userid" : "<username or user_id>"
575 "perm" : "(repository.(none|read|write|admin))",
784 "perm" : "(repository.(none|read|write|admin))",
576 }
785 }
577
786
578 OUTPUT::
787 OUTPUT::
579
788
789 id : <id_given_in_input>
580 result: {
790 result: {
581 "msg" : "Granted perm: <perm> for user: <username> in repo: <reponame>"
791 "msg" : "Granted perm: `<perm>` for user: `<username>` in repo: `<reponame>`",
792 "success": true
582 }
793 }
583 error: null
794 error: null
584
795
@@ -596,14 +807,16 b' INPUT::'
596 api_key : "<api_key>"
807 api_key : "<api_key>"
597 method : "revoke_user_permission"
808 method : "revoke_user_permission"
598 args: {
809 args: {
599 "repo_name" : "<reponame>",
810 "repoid" : "<reponame or repo_id>"
600 "username" : "<username>",
811 "userid" : "<username or user_id>"
601 }
812 }
602
813
603 OUTPUT::
814 OUTPUT::
604
815
816 id : <id_given_in_input>
605 result: {
817 result: {
606 "msg" : "Revoked perm for user: <suername> in repo: <reponame>"
818 "msg" : "Revoked perm for user: `<username>` in repo: `<reponame>`",
819 "success": true
607 }
820 }
608 error: null
821 error: null
609
822
@@ -622,15 +835,17 b' INPUT::'
622 api_key : "<api_key>"
835 api_key : "<api_key>"
623 method : "grant_users_group_permission"
836 method : "grant_users_group_permission"
624 args: {
837 args: {
625 "repo_name" : "<reponame>",
838 "repoid" : "<reponame or repo_id>"
626 "group_name" : "<usersgroupname>",
839 "usersgroupid" : "<users group id or name>"
627 "perm" : "(repository.(none|read|write|admin))",
840 "perm" : "(repository.(none|read|write|admin))",
628 }
841 }
629
842
630 OUTPUT::
843 OUTPUT::
631
844
845 id : <id_given_in_input>
632 result: {
846 result: {
633 "msg" : "Granted perm: <perm> for group: <usersgroupname> in repo: <reponame>"
847 "msg" : "Granted perm: `<perm>` for group: `<usersgroupname>` in repo: `<reponame>`",
848 "success": true
634 }
849 }
635 error: null
850 error: null
636
851
@@ -647,13 +862,15 b' INPUT::'
647 api_key : "<api_key>"
862 api_key : "<api_key>"
648 method : "revoke_users_group_permission"
863 method : "revoke_users_group_permission"
649 args: {
864 args: {
650 "repo_name" : "<reponame>",
865 "repoid" : "<reponame or repo_id>"
651 "users_group" : "<usersgroupname>",
866 "usersgroupid" : "<users group id or name>"
652 }
867 }
653
868
654 OUTPUT::
869 OUTPUT::
655
870
871 id : <id_given_in_input>
656 result: {
872 result: {
657 "msg" : "Revoked perm for group: <usersgroupname> in repo: <reponame>"
873 "msg" : "Revoked perm for group: `<usersgroupname>` in repo: `<reponame>`",
874 "success": true
658 }
875 }
659 error: null No newline at end of file
876 error: null
@@ -4,6 +4,66 b''
4 Changelog
4 Changelog
5 =========
5 =========
6
6
7 1.4.0 (**2012-09-03**)
8 ----------------------
9
10 news
11 ++++
12
13 - new codereview system
14 - email map, allowing users to have multiple email addresses mapped into
15 their accounts
16 - improved git-hook system. Now all actions for git are logged into journal
17 including pushed revisions, user and IP address
18 - changed setup-app into setup-rhodecode and added default options to it.
19 - new git repos are created as bare now by default
20 - #464 added links to groups in permission box
21 - #465 mentions autocomplete inside comments boxes
22 - #469 added --update-only option to whoosh to re-index only given list
23 of repos in index
24 - rhodecode-api CLI client
25 - new git http protocol replaced buggy dulwich implementation.
26 Now based on pygrack & gitweb
27 - Improved RSS/ATOM feeds. Discoverable by browsers using proper headers, and
28 reformated based on user suggestions. Additional rss/atom feeds for user
29 journal
30 - various i18n improvements
31 - #478 permissions overview for admin in user edit view
32 - File view now displays small gravatars off all authors of given file
33 - Implemented landing revisions. Each repository will get landing_rev attribute
34 that defines 'default' revision/branch for generating readme files
35 - Implemented #509, RhodeCode enforces SSL for push/pulling if requested at
36 earliest possible call.
37 - Import remote svn repositories to mercurial using hgsubversion.
38 - Fixed #508 RhodeCode now has a option to explicitly set forking permissions
39 - RhodeCode can use alternative server for generating avatar icons
40 - implemented repositories locking. Pull locks, push unlocks. Also can be done
41 via API calls
42 - #538 form for permissions can handle multiple users at once
43
44 fixes
45 +++++
46
47 - improved translations
48 - fixes issue #455 Creating an archive generates an exception on Windows
49 - fixes #448 Download ZIP archive keeps file in /tmp open and results
50 in out of disk space
51 - fixes issue #454 Search results under Windows include proceeding
52 backslash
53 - fixed issue #450. Rhodecode no longer will crash when bad revision is
54 present in journal data.
55 - fix for issue #417, git execution was broken on windows for certain
56 commands.
57 - fixed #413. Don't disable .git directory for bare repos on deleting
58 - fixed issue #459. Changed the way of obtaining logger in reindex task.
59 - fixed #453 added ID field in whoosh SCHEMA that solves the issue of
60 reindexing modified files
61 - fixed #481 rhodecode emails are sent without Date header
62 - fixed #458 wrong count when no repos are present
63 - fixed issue #492 missing `\ No newline at end of file` test at the end of
64 new chunk in html diff
65 - full text search now works also for commit messages
66
7 1.3.6 (**2012-05-17**)
67 1.3.6 (**2012-05-17**)
8 ----------------------
68 ----------------------
9
69
@@ -54,8 +54,8 b" copyright = u'%s, Marcin Kuzminski' % (d"
54 # The short X.Y version.
54 # The short X.Y version.
55 root = os.path.dirname(os.path.dirname(__file__))
55 root = os.path.dirname(os.path.dirname(__file__))
56 sys.path.append(root)
56 sys.path.append(root)
57 from rhodecode import get_version, __version__
57 from rhodecode import __version__
58 version = get_version()
58 version = __version__
59 # The full version, including alpha/beta/rc tags.
59 # The full version, including alpha/beta/rc tags.
60 release = __version__
60 release = __version__
61
61
@@ -27,7 +27,8 b' enviroment.'
27
27
28
28
29 After finishing your changes make sure all tests passes ok. You can run
29 After finishing your changes make sure all tests passes ok. You can run
30 the testsuite running nosetest from the project root.
30 the testsuite running ``nosetest`` from the project root, or if you use tox
31 run tox for python2.5-2.7 with multiple database test.
31
32
32 | Thank you for any contributions!
33 | Thank you for any contributions!
33 | Marcin
34 | Marcin
@@ -21,9 +21,12 b' Users Guide'
21
21
22 usage/general
22 usage/general
23 usage/git_support
23 usage/git_support
24 usage/performance
25 usage/locking
24 usage/statistics
26 usage/statistics
25 usage/backup
27 usage/backup
26 usage/debugging
28 usage/debugging
29 usage/troubleshooting
27
30
28 **Develop**
31 **Develop**
29
32
@@ -25,13 +25,18 b' Or::'
25 pip install rhodecode
25 pip install rhodecode
26
26
27 If you prefer to install RhodeCode manually simply grab latest release from
27 If you prefer to install RhodeCode manually simply grab latest release from
28 http://pypi.python.org/pypi/rhodecode, decompress the archive and run::
28 http://pypi.python.org/pypi/RhodeCode, decompress the archive and run::
29
29
30 python setup.py install
30 python setup.py install
31
31
32 Step by step installation example for Windows
33 ---------------------------------------------
32
34
33 Step by step installation example
35 :ref:`installation_win`
34 ---------------------------------
36
37
38 Step by step installation example for Linux
39 -------------------------------------------
35
40
36
41
37 For installing RhodeCode i highly recommend using separate virtualenv_. This
42 For installing RhodeCode i highly recommend using separate virtualenv_. This
@@ -41,7 +46,7 b' python and making things less problemati'
41 - Assuming you have installed virtualenv_ create a new virtual environment
46 - Assuming you have installed virtualenv_ create a new virtual environment
42 using virtualenv command::
47 using virtualenv command::
43
48
44 virtualenv --no-site-packages /var/www/rhodecode-venv
49 virtualenv --no-site-packages /opt/rhodecode-venv
45
50
46
51
47 .. note:: Using ``--no-site-packages`` when generating your
52 .. note:: Using ``--no-site-packages`` when generating your
@@ -54,10 +59,10 b' python and making things less problemati'
54 Python's "main" site-packages dir.
59 Python's "main" site-packages dir.
55
60
56
61
57 - this will install new virtualenv_ into `/var/www/rhodecode-venv`.
62 - this will install new virtualenv_ into `/opt/rhodecode-venv`.
58 - Activate the virtualenv_ by running::
63 - Activate the virtualenv_ by running::
59
64
60 source /var/www/rhodecode-venv/bin/activate
65 source /opt/rhodecode-venv/bin/activate
61
66
62 .. note:: If you're using UNIX, *do not* use ``sudo`` to run the
67 .. note:: If you're using UNIX, *do not* use ``sudo`` to run the
63 ``virtualenv`` script. It's perfectly acceptable (and desirable)
68 ``virtualenv`` script. It's perfectly acceptable (and desirable)
@@ -66,7 +71,7 b' python and making things less problemati'
66 - Make a folder for rhodecode data files, and configuration somewhere on the
71 - Make a folder for rhodecode data files, and configuration somewhere on the
67 filesystem. For example::
72 filesystem. For example::
68
73
69 mkdir /var/www/rhodecode
74 mkdir /opt/rhodecode
70
75
71
76
72 - Go into the created directory run this command to install rhodecode::
77 - Go into the created directory run this command to install rhodecode::
@@ -34,6 +34,11 b' entering this "root" path ``setup-rhodec'
34 and password for the initial admin account which ``setup-rhodecode`` sets
34 and password for the initial admin account which ``setup-rhodecode`` sets
35 up for you.
35 up for you.
36
36
37 setup process can be fully automated, example for lazy::
38
39 paster setup-rhodecode production.ini --user=marcink --password=secret --email=marcin@rhodecode.org --repos=/home/marcink/my_repos
40
41
37 - The ``setup-rhodecode`` command will create all of the needed tables and an
42 - The ``setup-rhodecode`` command will create all of the needed tables and an
38 admin account. When choosing a root path you can either use a new empty
43 admin account. When choosing a root path you can either use a new empty
39 location, or a location which already contains existing repositories. If you
44 location, or a location which already contains existing repositories. If you
@@ -527,6 +532,18 b' Sample config for nginx using proxy::'
527 access_log /var/log/nginx/rhodecode.access.log;
532 access_log /var/log/nginx/rhodecode.access.log;
528 error_log /var/log/nginx/rhodecode.error.log;
533 error_log /var/log/nginx/rhodecode.error.log;
529
534
535 # uncomment if you have nginx with chunking module compiled
536 # fixes the issues of having to put postBuffer data for large git
537 # pushes
538 #chunkin on;
539 #error_page 411 = @my_411_error;
540 #location @my_411_error {
541 # chunkin_resume;
542 #}
543
544 # uncomment if you want to serve static files by nginx
545 #root /path/to/installation/rhodecode/public;
546
530 location / {
547 location / {
531 try_files $uri @rhode;
548 try_files $uri @rhode;
532 }
549 }
@@ -682,43 +699,9 b' environment.'
682 Other configuration files
699 Other configuration files
683 -------------------------
700 -------------------------
684
701
685 Some example init.d scripts can be found here, for debian and gentoo:
702 Some example init.d scripts can be found in init.d directory::
686
687 https://rhodecode.org/rhodecode/files/tip/init.d
688
689
690 Troubleshooting
691 ---------------
692
693 :Q: **Missing static files?**
694 :A: Make sure either to set the `static_files = true` in the .ini file or
695 double check the root path for your http setup. It should point to
696 for example:
697 /home/my-virtual-python/lib/python2.6/site-packages/rhodecode/public
698
699 |
700
701 :Q: **Can't install celery/rabbitmq**
702 :A: Don't worry RhodeCode works without them too. No extra setup is required.
703
703
704 |
704 https://secure.rhodecode.org/rhodecode/files/beta/init.d
705
706 :Q: **Long lasting push timeouts?**
707 :A: Make sure you set a longer timeouts in your proxy/fcgi settings, timeouts
708 are caused by https server and not RhodeCode.
709
710 |
711
712 :Q: **Large pushes timeouts?**
713 :A: Make sure you set a proper max_body_size for the http server.
714
715 |
716
717 :Q: **Apache doesn't pass basicAuth on pull/push?**
718 :A: Make sure you added `WSGIPassAuthorization true`.
719
720 For further questions search the `Issues tracker`_, or post a message in the
721 `google group rhodecode`_
722
705
723 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
706 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
724 .. _python: http://www.python.org/
707 .. _python: http://www.python.org/
@@ -729,4 +712,4 b' For further questions search the `Issues'
729 .. _mercurial-server: http://www.lshift.net/mercurial-server.html
712 .. _mercurial-server: http://www.lshift.net/mercurial-server.html
730 .. _PublishingRepositories: http://mercurial.selenic.com/wiki/PublishingRepositories
713 .. _PublishingRepositories: http://mercurial.selenic.com/wiki/PublishingRepositories
731 .. _Issues tracker: https://bitbucket.org/marcinkuzminski/rhodecode/issues
714 .. _Issues tracker: https://bitbucket.org/marcinkuzminski/rhodecode/issues
732 .. _google group rhodecode: http://groups.google.com/group/rhodecode
715 .. _google group rhodecode: http://groups.google.com/group/rhodecode No newline at end of file
@@ -62,7 +62,6 b' the _<ID> syntax can be used anywhere in'
62 for changelogs, files and other can be exchanged with _<ID> syntax.
62 for changelogs, files and other can be exchanged with _<ID> syntax.
63
63
64
64
65
66 Mailing
65 Mailing
67 -------
66 -------
68
67
@@ -82,4 +81,27 b' Trending source files'
82 Trending source files are calculated based on pre defined dict of known
81 Trending source files are calculated based on pre defined dict of known
83 types and extensions. If You miss some extension or Would like to scan some
82 types and extensions. If You miss some extension or Would like to scan some
84 custom files it's possible to add new types in `LANGUAGES_EXTENSIONS_MAP` dict
83 custom files it's possible to add new types in `LANGUAGES_EXTENSIONS_MAP` dict
85 located in `/rhodecode/lib/celerylib/tasks.py` No newline at end of file
84 located in `/rhodecode/lib/celerylib/tasks.py`
85
86
87 Cloning remote repositories
88 ---------------------------
89
90 RhodeCode has an ability to clone remote repos from given remote locations.
91 Currently it support following options:
92
93 - hg -> hg clone
94 - svn -> hg clone
95 - git -> git clone
96
97
98 .. note::
99
100 - *`svn -> hg` cloning requires `hgsubversion` library to be installed.*
101
102 If you need to clone repositories that are protected via basic auth, you
103 might pass the url with stored credentials inside eg.
104 `http://user:passw@remote.server/repo, RhodeCode will try to login and clone
105 using given credentials. Please take a note that they will be stored as
106 plaintext inside the database. RhodeCode will remove auth info when showing the
107 clone url in summary page.
@@ -5,11 +5,13 b' GIT support'
5 ===========
5 ===========
6
6
7
7
8 Git support in RhodeCode 1.3 was enabled by default.
8 Git support in RhodeCode 1.3 was enabled by default. You need to have a git
9 client installed on the machine to make git fully work.
10
9 Although There are some limitations on git usage.
11 Although There are some limitations on git usage.
10
12
11 - No hooks are runned for git push/pull actions.
13 - hooks that are executed on pull/push are not *real* hooks, they are
12 - logs in action journals don't have git operations
14 just emulating the behavior, and are executed **BEFORE** action takes place.
13 - large pushes needs http server with chunked encoding support.
15 - large pushes needs http server with chunked encoding support.
14
16
15 if you plan to use git you need to run RhodeCode with some
17 if you plan to use git you need to run RhodeCode with some
@@ -17,14 +19,19 b' http server that supports chunked encodi'
17 i recommend using waitress_ or gunicorn_ (linux only) for `paste` wsgi app
19 i recommend using waitress_ or gunicorn_ (linux only) for `paste` wsgi app
18 replacement.
20 replacement.
19
21
20 To use waitress simply change change the following in the .ini file::
22 To use, simply change change the following in the .ini file::
21
23
22 use = egg:Paste#http
24 use = egg:Paste#http
23
25
24 To::
26 to::
25
27
26 use = egg:waitress#main
28 use = egg:waitress#main
27
29
30 or::
31
32 use = egg:gunicorn#main
33
34
28 And comment out bellow options::
35 And comment out bellow options::
29
36
30 threadpool_workers =
37 threadpool_workers =
@@ -30,22 +30,31 b' pdebug = false'
30
30
31 [server:main]
31 [server:main]
32 ##nr of threads to spawn
32 ##nr of threads to spawn
33 threadpool_workers = 5
33 #threadpool_workers = 5
34
34
35 ##max request before thread respawn
35 ##max request before thread respawn
36 threadpool_max_requests = 10
36 #threadpool_max_requests = 10
37
37
38 ##option to use threads of process
38 ##option to use threads of process
39 use_threadpool = true
39 #use_threadpool = true
40
40
41 use = egg:Paste#http
41 #use = egg:Paste#http
42 use = egg:waitress#main
42 host = 127.0.0.1
43 host = 127.0.0.1
43 port = 8001
44 port = 8001
44
45
46 [filter:proxy-prefix]
47 # prefix middleware for rc
48 use = egg:PasteDeploy#prefix
49 prefix = /<your-prefix>
50
45 [app:main]
51 [app:main]
46 use = egg:rhodecode
52 use = egg:rhodecode
53 #filter-with = proxy-prefix
47 full_stack = true
54 full_stack = true
48 static_files = true
55 static_files = true
56 # Optional Languages
57 # en, fr, ja, pt_BR, zh_CN, zh_TW
49 lang = en
58 lang = en
50 cache_dir = %(here)s/data
59 cache_dir = %(here)s/data
51 index_dir = %(here)s/data/index
60 index_dir = %(here)s/data/index
@@ -54,6 +63,15 b' cut_off_limit = 256000'
54 force_https = false
63 force_https = false
55 commit_parse_limit = 50
64 commit_parse_limit = 50
56 use_gravatar = true
65 use_gravatar = true
66
67 ## alternative_gravatar_url allows you to use your own avatar server application
68 ## the following parts of the URL will be replaced
69 ## {email} user email
70 ## {md5email} md5 hash of the user email (like at gravatar.com)
71 ## {size} size of the image that is expected from the server application
72 #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size}
73 #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size}
74
57 container_auth_enabled = false
75 container_auth_enabled = false
58 proxypass_auth_enabled = false
76 proxypass_auth_enabled = false
59 default_encoding = utf8
77 default_encoding = utf8
@@ -78,7 +96,8 b' default_encoding = utf8'
78 issue_pat = (?:\s*#)(\d+)
96 issue_pat = (?:\s*#)(\d+)
79
97
80 ## server url to the issue, each {id} will be replaced with match
98 ## server url to the issue, each {id} will be replaced with match
81 ## fetched from the regex and {repo} is replaced with repository name
99 ## fetched from the regex and {repo} is replaced with full repository name
100 ## including groups {repo_name} is replaced with just name of repo
82
101
83 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
102 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
84
103
@@ -165,30 +184,34 b' beaker.cache.sql_cache_long.key_length ='
165 ## The storage uses the Container API
184 ## The storage uses the Container API
166 ## that is also used by the cache system.
185 ## that is also used by the cache system.
167
186
168 ## db session example
187 ## db session ##
169
170 #beaker.session.type = ext:database
188 #beaker.session.type = ext:database
171 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
189 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
172 #beaker.session.table_name = db_session
190 #beaker.session.table_name = db_session
173
191
174 ## encrypted cookie session, good for many instances
192 ## encrypted cookie client side session, good for many instances ##
175 #beaker.session.type = cookie
193 #beaker.session.type = cookie
176
194
177 beaker.session.type = file
195 ## file based cookies (default) ##
196 #beaker.session.type = file
197
198
178 beaker.session.key = rhodecode
199 beaker.session.key = rhodecode
179 # secure cookie requires AES python libraries
200 ## secure cookie requires AES python libraries ##
180 #beaker.session.encrypt_key = g654dcno0-9873jhgfreyu
201 #beaker.session.encrypt_key = g654dcno0-9873jhgfreyu
181 #beaker.session.validate_key = 9712sds2212c--zxc123
202 #beaker.session.validate_key = 9712sds2212c--zxc123
182 beaker.session.timeout = 36000
203 ## sets session as invalid if it haven't been accessed for given amount of time
204 beaker.session.timeout = 2592000
183 beaker.session.httponly = true
205 beaker.session.httponly = true
206 #beaker.session.cookie_path = /<your-prefix>
184
207
185 ## uncomment for https secure cookie
208 ## uncomment for https secure cookie ##
186 beaker.session.secure = false
209 beaker.session.secure = false
187
210
188 ##auto save the session to not to use .save()
211 ## auto save the session to not to use .save() ##
189 beaker.session.auto = False
212 beaker.session.auto = False
190
213
191 ##true exire at browser close
214 ## default cookie expiration time in seconds `true` expire at browser close ##
192 #beaker.session.cookie_expires = 3600
215 #beaker.session.cookie_expires = 3600
193
216
194
217
@@ -1,18 +1,20 b''
1 waitress==0.8.1
2 webob==1.0.8
1 Pylons==1.0.0
3 Pylons==1.0.0
2 Beaker==1.6.3
4 Beaker==1.6.4
3 WebHelpers==1.3
5 WebHelpers==1.3
4 formencode==1.2.4
6 formencode==1.2.4
5 SQLAlchemy==0.7.6
7 SQLAlchemy==0.7.8
6 Mako==0.7.0
8 Mako==0.7.2
7 pygments>=1.4
9 pygments>=1.5
8 whoosh>=2.4.0,<2.5
10 whoosh>=2.4.0,<2.5
9 celery>=2.2.5,<2.3
11 celery>=2.2.5,<2.3
10 babel
12 babel
11 python-dateutil>=1.5.0,<2.0.0
13 python-dateutil>=1.5.0,<2.0.0
12 dulwich>=0.8.5,<0.9.0
14 dulwich>=0.8.5,<0.9.0
13 webob==1.0.8
14 markdown==2.1.1
15 markdown==2.1.1
15 docutils==0.8.1
16 docutils==0.8.1
16 simplejson==2.5.2
17 simplejson==2.5.2
18 mock
17 py-bcrypt
19 py-bcrypt
18 mercurial>=2.2.1,<2.3 No newline at end of file
20 mercurial>=2.3.0,<2.4 No newline at end of file
@@ -26,7 +26,7 b''
26 import sys
26 import sys
27 import platform
27 import platform
28
28
29 VERSION = (1, 3, 6)
29 VERSION = (1, 4, 0)
30
30
31 try:
31 try:
32 from rhodecode.lib import get_current_revision
32 from rhodecode.lib import get_current_revision
@@ -38,50 +38,19 b' except ImportError:'
38
38
39 __version__ = ('.'.join((str(each) for each in VERSION[:3])) +
39 __version__ = ('.'.join((str(each) for each in VERSION[:3])) +
40 '.'.join(VERSION[3:]))
40 '.'.join(VERSION[3:]))
41 __dbversion__ = 5 # defines current db version for migrations
41 __dbversion__ = 6 # defines current db version for migrations
42 __platform__ = platform.system()
42 __platform__ = platform.system()
43 __license__ = 'GPLv3'
43 __license__ = 'GPLv3'
44 __py_version__ = sys.version_info
44 __py_version__ = sys.version_info
45 __author__ = 'Marcin Kuzminski'
46 __url__ = 'http://rhodecode.org'
45
47
46 PLATFORM_WIN = ('Windows')
48 PLATFORM_WIN = ('Windows')
47 PLATFORM_OTHERS = ('Linux', 'Darwin', 'FreeBSD', 'OpenBSD', 'SunOS')
49 PLATFORM_OTHERS = ('Linux', 'Darwin', 'FreeBSD', 'OpenBSD', 'SunOS') #depracated
48
50
49 is_windows = __platform__ in PLATFORM_WIN
51 is_windows = __platform__ in PLATFORM_WIN
50 is_unix = __platform__ in PLATFORM_OTHERS
52 is_unix = not is_windows
51
53
52 requirements = [
53 "Pylons==1.0.0",
54 "Beaker==1.6.3",
55 "WebHelpers==1.3",
56 "formencode==1.2.4",
57 "SQLAlchemy==0.7.6",
58 "Mako==0.7.0",
59 "pygments>=1.4",
60 "whoosh>=2.4.0,<2.5",
61 "celery>=2.2.5,<2.3",
62 "babel",
63 "python-dateutil>=1.5.0,<2.0.0",
64 "dulwich>=0.8.5,<0.9.0",
65 "webob==1.0.8",
66 "markdown==2.1.1",
67 "docutils==0.8.1",
68 "simplejson==2.5.2",
69 ]
70
71 if __py_version__ < (2, 6):
72 requirements.append("pysqlite")
73
74 if is_windows:
75 requirements.append("mercurial>=2.2.1,<2.3")
76 else:
77 requirements.append("py-bcrypt")
78 requirements.append("mercurial>=2.2.1,<2.3")
79
80
81 def get_version():
82 """Returns shorter version (digit parts only) as string."""
83
84 return '.'.join((str(each) for each in VERSION[:3]))
85
54
86 BACKENDS = {
55 BACKENDS = {
87 'hg': 'Mercurial repository',
56 'hg': 'Mercurial repository',
@@ -1,9 +1,9 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.backup_manager
3 rhodecode.bin.backup_manager
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Mercurial repositories backup manager, it allows to backups all
6 Repositories backup manager, it allows to backups all
7 repositories and send it to backup server using RSA key via ssh.
7 repositories and send it to backup server using RSA key via ssh.
8
8
9 :created_on: Feb 28, 2010
9 :created_on: Feb 28, 2010
@@ -39,7 +39,7 b' logging.basicConfig(level=logging.DEBUG,'
39 class BackupManager(object):
39 class BackupManager(object):
40 def __init__(self, repos_location, rsa_key, backup_server):
40 def __init__(self, repos_location, rsa_key, backup_server):
41 today = datetime.datetime.now().weekday() + 1
41 today = datetime.datetime.now().weekday() + 1
42 self.backup_file_name = "mercurial_repos.%s.tar.gz" % today
42 self.backup_file_name = "rhodecode_repos.%s.tar.gz" % today
43
43
44 self.id_rsa_path = self.get_id_rsa(rsa_key)
44 self.id_rsa_path = self.get_id_rsa(rsa_key)
45 self.repos_path = self.get_repos_path(repos_location)
45 self.repos_path = self.get_repos_path(repos_location)
@@ -30,22 +30,31 b' pdebug = false'
30
30
31 [server:main]
31 [server:main]
32 ##nr of threads to spawn
32 ##nr of threads to spawn
33 threadpool_workers = 5
33 #threadpool_workers = 5
34
34
35 ##max request before thread respawn
35 ##max request before thread respawn
36 threadpool_max_requests = 10
36 #threadpool_max_requests = 10
37
37
38 ##option to use threads of process
38 ##option to use threads of process
39 use_threadpool = true
39 #use_threadpool = true
40
40
41 use = egg:Paste#http
41 #use = egg:Paste#http
42 use = egg:waitress#main
42 host = 127.0.0.1
43 host = 127.0.0.1
43 port = 5000
44 port = 5000
44
45
46 [filter:proxy-prefix]
47 # prefix middleware for rc
48 use = egg:PasteDeploy#prefix
49 prefix = /<your-prefix>
50
45 [app:main]
51 [app:main]
46 use = egg:rhodecode
52 use = egg:rhodecode
53 #filter-with = proxy-prefix
47 full_stack = true
54 full_stack = true
48 static_files = true
55 static_files = true
56 # Optional Languages
57 # en, fr, ja, pt_BR, zh_CN, zh_TW
49 lang = en
58 lang = en
50 cache_dir = %(here)s/data
59 cache_dir = %(here)s/data
51 index_dir = %(here)s/data/index
60 index_dir = %(here)s/data/index
@@ -54,6 +63,15 b' cut_off_limit = 256000'
54 force_https = false
63 force_https = false
55 commit_parse_limit = 50
64 commit_parse_limit = 50
56 use_gravatar = true
65 use_gravatar = true
66
67 ## alternative_gravatar_url allows you to use your own avatar server application
68 ## the following parts of the URL will be replaced
69 ## {email} user email
70 ## {md5email} md5 hash of the user email (like at gravatar.com)
71 ## {size} size of the image that is expected from the server application
72 #alternative_gravatar_url = http://myavatarserver.com/getbyemail/{email}/{size}
73 #alternative_gravatar_url = http://myavatarserver.com/getbymd5/{md5email}?s={size}
74
57 container_auth_enabled = false
75 container_auth_enabled = false
58 proxypass_auth_enabled = false
76 proxypass_auth_enabled = false
59 default_encoding = utf8
77 default_encoding = utf8
@@ -78,7 +96,8 b' default_encoding = utf8'
78 issue_pat = (?:\s*#)(\d+)
96 issue_pat = (?:\s*#)(\d+)
79
97
80 ## server url to the issue, each {id} will be replaced with match
98 ## server url to the issue, each {id} will be replaced with match
81 ## fetched from the regex and {repo} is replaced with repository name
99 ## fetched from the regex and {repo} is replaced with full repository name
100 ## including groups {repo_name} is replaced with just name of repo
82
101
83 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
102 issue_server_link = https://myissueserver.com/{repo}/issue/{id}
84
103
@@ -165,30 +184,34 b' beaker.cache.sql_cache_long.key_length ='
165 ## The storage uses the Container API
184 ## The storage uses the Container API
166 ## that is also used by the cache system.
185 ## that is also used by the cache system.
167
186
168 ## db session example
187 ## db session ##
169
170 #beaker.session.type = ext:database
188 #beaker.session.type = ext:database
171 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
189 #beaker.session.sa.url = postgresql://postgres:qwe@localhost/rhodecode
172 #beaker.session.table_name = db_session
190 #beaker.session.table_name = db_session
173
191
174 ## encrypted cookie session, good for many instances
192 ## encrypted cookie client side session, good for many instances ##
175 #beaker.session.type = cookie
193 #beaker.session.type = cookie
176
194
177 beaker.session.type = file
195 ## file based cookies (default) ##
196 #beaker.session.type = file
197
198
178 beaker.session.key = rhodecode
199 beaker.session.key = rhodecode
179 # secure cookie requires AES python libraries
200 ## secure cookie requires AES python libraries ##
180 #beaker.session.encrypt_key = ${app_instance_secret}
201 #beaker.session.encrypt_key = g654dcno0-9873jhgfreyu
181 #beaker.session.validate_key = ${app_instance_secret}
202 #beaker.session.validate_key = 9712sds2212c--zxc123
182 beaker.session.timeout = 36000
203 ## sets session as invalid if it haven't been accessed for given amount of time
204 beaker.session.timeout = 2592000
183 beaker.session.httponly = true
205 beaker.session.httponly = true
206 #beaker.session.cookie_path = /<your-prefix>
184
207
185 ## uncomment for https secure cookie
208 ## uncomment for https secure cookie ##
186 beaker.session.secure = false
209 beaker.session.secure = false
187
210
188 ##auto save the session to not to use .save()
211 ## auto save the session to not to use .save() ##
189 beaker.session.auto = False
212 beaker.session.auto = False
190
213
191 ##true exire at browser close
214 ## default cookie expiration time in seconds `true` expire at browser close ##
192 #beaker.session.cookie_expires = 3600
215 #beaker.session.cookie_expires = 3600
193
216
194
217
@@ -72,19 +72,28 b' def load_environment(global_conf, app_co'
72 config['pylons.strict_tmpl_context'] = True
72 config['pylons.strict_tmpl_context'] = True
73 test = os.path.split(config['__file__'])[-1] == 'test.ini'
73 test = os.path.split(config['__file__'])[-1] == 'test.ini'
74 if test:
74 if test:
75 if os.environ.get('TEST_DB'):
76 # swap config if we pass enviroment variable
77 config['sqlalchemy.db1.url'] = os.environ.get('TEST_DB')
78
75 from rhodecode.lib.utils import create_test_env, create_test_index
79 from rhodecode.lib.utils import create_test_env, create_test_index
76 from rhodecode.tests import TESTS_TMP_PATH
80 from rhodecode.tests import TESTS_TMP_PATH
77 create_test_env(TESTS_TMP_PATH, config)
81 # set RC_NO_TMP_PATH=1 to disable re-creating the database and
78 create_test_index(TESTS_TMP_PATH, config, True)
82 # test repos
83 if not int(os.environ.get('RC_NO_TMP_PATH', 0)):
84 create_test_env(TESTS_TMP_PATH, config)
85 # set RC_WHOOSH_TEST_DISABLE=1 to disable whoosh index during tests
86 if not int(os.environ.get('RC_WHOOSH_TEST_DISABLE', 0)):
87 create_test_index(TESTS_TMP_PATH, config, True)
79
88
80 # MULTIPLE DB configs
89 # MULTIPLE DB configs
81 # Setup the SQLAlchemy database engine
90 # Setup the SQLAlchemy database engine
82 sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.')
91 sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.')
83
84 init_model(sa_engine_db1)
92 init_model(sa_engine_db1)
85
93
86 repos_path = make_ui('db').configitems('paths')[0][1]
94 repos_path = make_ui('db').configitems('paths')[0][1]
87 repo2db_mapper(ScmModel().repo_scan(repos_path))
95 repo2db_mapper(ScmModel().repo_scan(repos_path),
96 remove_obsolete=False, install_git_hook=False)
88 set_available_permissions(config)
97 set_available_permissions(config)
89 config['base_path'] = repos_path
98 config['base_path'] = repos_path
90 set_rhodecode_config(config)
99 set_rhodecode_config(config)
@@ -1,6 +1,7 b''
1 # Additional mappings that are not present in the pygments lexers
1 # Additional mappings that are not present in the pygments lexers
2 # used for building stats
2 # used for building stats
3 # format is {'ext':'Name'} eg. {'py':'Python'}
3 # format is {'ext':['Names']} eg. {'py':['Python']} note: there can be
4 # more than one name for extension
4 # NOTE: that this will overide any mappings in LANGUAGES_EXTENSIONS_MAP
5 # NOTE: that this will overide any mappings in LANGUAGES_EXTENSIONS_MAP
5 # build by pygments
6 # build by pygments
6 EXTRA_MAPPINGS = {}
7 EXTRA_MAPPINGS = {}
@@ -39,6 +40,7 b' def _crhook(*args, **kwargs):'
39 :param group_id:
40 :param group_id:
40 :param created_by:
41 :param created_by:
41 """
42 """
43
42 return 0
44 return 0
43 CREATE_REPO_HOOK = _crhook
45 CREATE_REPO_HOOK = _crhook
44
46
@@ -54,7 +54,7 b' class MakeRcExt(BasePasterCommand):'
54 logging.config.fileConfig(self.path_to_ini_file)
54 logging.config.fileConfig(self.path_to_ini_file)
55 from pylons import config
55 from pylons import config
56
56
57 def _make_file(ext_file):
57 def _make_file(ext_file, tmpl):
58 bdir = os.path.split(ext_file)[0]
58 bdir = os.path.split(ext_file)[0]
59 if not os.path.isdir(bdir):
59 if not os.path.isdir(bdir):
60 os.makedirs(bdir)
60 os.makedirs(bdir)
@@ -71,11 +71,11 b' class MakeRcExt(BasePasterCommand):'
71 msg = ('Extension file already exists, do you want '
71 msg = ('Extension file already exists, do you want '
72 'to overwrite it ? [y/n]')
72 'to overwrite it ? [y/n]')
73 if ask_ok(msg):
73 if ask_ok(msg):
74 _make_file(ext_file)
74 _make_file(ext_file, tmpl)
75 else:
75 else:
76 log.info('nothing done...')
76 log.info('nothing done...')
77 else:
77 else:
78 _make_file(ext_file)
78 _make_file(ext_file, tmpl)
79
79
80 def update_parser(self):
80 def update_parser(self):
81 pass
81 pass
@@ -69,7 +69,7 b' def make_map(config):'
69 rmap.connect('home', '/', controller='home', action='index')
69 rmap.connect('home', '/', controller='home', action='index')
70 rmap.connect('repo_switcher', '/repos', controller='home',
70 rmap.connect('repo_switcher', '/repos', controller='home',
71 action='repo_switcher')
71 action='repo_switcher')
72 rmap.connect('branch_tag_switcher', '/branches-tags/{repo_name:.*}',
72 rmap.connect('branch_tag_switcher', '/branches-tags/{repo_name:.*?}',
73 controller='home', action='branch_tag_switcher')
73 controller='home', action='branch_tag_switcher')
74 rmap.connect('bugtracker',
74 rmap.connect('bugtracker',
75 "http://bitbucket.org/marcinkuzminski/rhodecode/issues",
75 "http://bitbucket.org/marcinkuzminski/rhodecode/issues",
@@ -93,52 +93,54 b' def make_map(config):'
93 action="new", conditions=dict(method=["GET"]))
93 action="new", conditions=dict(method=["GET"]))
94 m.connect("formatted_new_repo", "/repos/new.{format}",
94 m.connect("formatted_new_repo", "/repos/new.{format}",
95 action="new", conditions=dict(method=["GET"]))
95 action="new", conditions=dict(method=["GET"]))
96 m.connect("/repos/{repo_name:.*}",
96 m.connect("/repos/{repo_name:.*?}",
97 action="update", conditions=dict(method=["PUT"],
97 action="update", conditions=dict(method=["PUT"],
98 function=check_repo))
98 function=check_repo))
99 m.connect("/repos/{repo_name:.*}",
99 m.connect("/repos/{repo_name:.*?}",
100 action="delete", conditions=dict(method=["DELETE"],
100 action="delete", conditions=dict(method=["DELETE"],
101 function=check_repo))
101 function=check_repo))
102 m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
102 m.connect("edit_repo", "/repos/{repo_name:.*?}/edit",
103 action="edit", conditions=dict(method=["GET"],
103 action="edit", conditions=dict(method=["GET"],
104 function=check_repo))
104 function=check_repo))
105 m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
105 m.connect("formatted_edit_repo", "/repos/{repo_name:.*?}.{format}/edit",
106 action="edit", conditions=dict(method=["GET"],
106 action="edit", conditions=dict(method=["GET"],
107 function=check_repo))
107 function=check_repo))
108 m.connect("repo", "/repos/{repo_name:.*}",
108 m.connect("repo", "/repos/{repo_name:.*?}",
109 action="show", conditions=dict(method=["GET"],
109 action="show", conditions=dict(method=["GET"],
110 function=check_repo))
110 function=check_repo))
111 m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
111 m.connect("formatted_repo", "/repos/{repo_name:.*?}.{format}",
112 action="show", conditions=dict(method=["GET"],
112 action="show", conditions=dict(method=["GET"],
113 function=check_repo))
113 function=check_repo))
114 #ajax delete repo perm user
114 #ajax delete repo perm user
115 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
115 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*?}",
116 action="delete_perm_user",
116 action="delete_perm_user",
117 conditions=dict(method=["DELETE"], function=check_repo))
117 conditions=dict(method=["DELETE"], function=check_repo))
118
118
119 #ajax delete repo perm users_group
119 #ajax delete repo perm users_group
120 m.connect('delete_repo_users_group',
120 m.connect('delete_repo_users_group',
121 "/repos_delete_users_group/{repo_name:.*}",
121 "/repos_delete_users_group/{repo_name:.*?}",
122 action="delete_perm_users_group",
122 action="delete_perm_users_group",
123 conditions=dict(method=["DELETE"], function=check_repo))
123 conditions=dict(method=["DELETE"], function=check_repo))
124
124
125 #settings actions
125 #settings actions
126 m.connect('repo_stats', "/repos_stats/{repo_name:.*}",
126 m.connect('repo_stats', "/repos_stats/{repo_name:.*?}",
127 action="repo_stats", conditions=dict(method=["DELETE"],
127 action="repo_stats", conditions=dict(method=["DELETE"],
128 function=check_repo))
128 function=check_repo))
129 m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
129 m.connect('repo_cache', "/repos_cache/{repo_name:.*?}",
130 action="repo_cache", conditions=dict(method=["DELETE"],
130 action="repo_cache", conditions=dict(method=["DELETE"],
131 function=check_repo))
131 function=check_repo))
132 m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*}",
132 m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*?}",
133 action="repo_public_journal", conditions=dict(method=["PUT"],
133 action="repo_public_journal", conditions=dict(method=["PUT"],
134 function=check_repo))
134 function=check_repo))
135 m.connect('repo_pull', "/repo_pull/{repo_name:.*}",
135 m.connect('repo_pull', "/repo_pull/{repo_name:.*?}",
136 action="repo_pull", conditions=dict(method=["PUT"],
136 action="repo_pull", conditions=dict(method=["PUT"],
137 function=check_repo))
137 function=check_repo))
138 m.connect('repo_as_fork', "/repo_as_fork/{repo_name:.*}",
138 m.connect('repo_as_fork', "/repo_as_fork/{repo_name:.*?}",
139 action="repo_as_fork", conditions=dict(method=["PUT"],
139 action="repo_as_fork", conditions=dict(method=["PUT"],
140 function=check_repo))
140 function=check_repo))
141
141 m.connect('repo_locking', "/repo_locking/{repo_name:.*?}",
142 action="repo_locking", conditions=dict(method=["PUT"],
143 function=check_repo))
142 with rmap.submapper(path_prefix=ADMIN_PREFIX,
144 with rmap.submapper(path_prefix=ADMIN_PREFIX,
143 controller='admin/repos_groups') as m:
145 controller='admin/repos_groups') as m:
144 m.connect("repos_groups", "/repos_groups",
146 m.connect("repos_groups", "/repos_groups",
@@ -157,9 +159,8 b' def make_map(config):'
157 m.connect("delete_repos_group", "/repos_groups/{id}",
159 m.connect("delete_repos_group", "/repos_groups/{id}",
158 action="delete", conditions=dict(method=["DELETE"],
160 action="delete", conditions=dict(method=["DELETE"],
159 function=check_int))
161 function=check_int))
160 m.connect("edit_repos_group", "/repos_groups/{id}/edit",
162 m.connect("edit_repos_group", "/repos_groups/{id:.*?}/edit",
161 action="edit", conditions=dict(method=["GET"],
163 action="edit", conditions=dict(method=["GET"],))
162 function=check_int))
163 m.connect("formatted_edit_repos_group",
164 m.connect("formatted_edit_repos_group",
164 "/repos_groups/{id}.{format}/edit",
165 "/repos_groups/{id}.{format}/edit",
165 action="edit", conditions=dict(method=["GET"],
166 action="edit", conditions=dict(method=["GET"],
@@ -212,8 +213,12 b' def make_map(config):'
212 #EXTRAS USER ROUTES
213 #EXTRAS USER ROUTES
213 m.connect("user_perm", "/users_perm/{id}",
214 m.connect("user_perm", "/users_perm/{id}",
214 action="update_perm", conditions=dict(method=["PUT"]))
215 action="update_perm", conditions=dict(method=["PUT"]))
216 m.connect("user_emails", "/users_emails/{id}",
217 action="add_email", conditions=dict(method=["PUT"]))
218 m.connect("user_emails_delete", "/users_emails/{id}",
219 action="delete_email", conditions=dict(method=["DELETE"]))
215
220
216 #ADMIN USERS REST ROUTES
221 #ADMIN USERS GROUPS REST ROUTES
217 with rmap.submapper(path_prefix=ADMIN_PREFIX,
222 with rmap.submapper(path_prefix=ADMIN_PREFIX,
218 controller='admin/users_groups') as m:
223 controller='admin/users_groups') as m:
219 m.connect("users_groups", "/users_groups",
224 m.connect("users_groups", "/users_groups",
@@ -292,6 +297,10 b' def make_map(config):'
292 action="my_account_update", conditions=dict(method=["PUT"]))
297 action="my_account_update", conditions=dict(method=["PUT"]))
293 m.connect("admin_settings_create_repository", "/create_repository",
298 m.connect("admin_settings_create_repository", "/create_repository",
294 action="create_repository", conditions=dict(method=["GET"]))
299 action="create_repository", conditions=dict(method=["GET"]))
300 m.connect("admin_settings_my_repos", "/my_account/repos",
301 action="my_account_my_repos", conditions=dict(method=["GET"]))
302 m.connect("admin_settings_my_pullrequests", "/my_account/pull_requests",
303 action="my_account_my_pullrequests", conditions=dict(method=["GET"]))
295
304
296 #NOTIFICATION REST ROUTES
305 #NOTIFICATION REST ROUTES
297 with rmap.submapper(path_prefix=ADMIN_PREFIX,
306 with rmap.submapper(path_prefix=ADMIN_PREFIX,
@@ -337,15 +346,27 b' def make_map(config):'
337 m.connect('api', '/api')
346 m.connect('api', '/api')
338
347
339 #USER JOURNAL
348 #USER JOURNAL
340 rmap.connect('journal', '%s/journal' % ADMIN_PREFIX, controller='journal')
349 rmap.connect('journal', '%s/journal' % ADMIN_PREFIX,
350 controller='journal', action='index')
351 rmap.connect('journal_rss', '%s/journal/rss' % ADMIN_PREFIX,
352 controller='journal', action='journal_rss')
353 rmap.connect('journal_atom', '%s/journal/atom' % ADMIN_PREFIX,
354 controller='journal', action='journal_atom')
341
355
342 rmap.connect('public_journal', '%s/public_journal' % ADMIN_PREFIX,
356 rmap.connect('public_journal', '%s/public_journal' % ADMIN_PREFIX,
343 controller='journal', action="public_journal")
357 controller='journal', action="public_journal")
344
358
345 rmap.connect('public_journal_rss', '%s/public_journal_rss' % ADMIN_PREFIX,
359 rmap.connect('public_journal_rss', '%s/public_journal/rss' % ADMIN_PREFIX,
360 controller='journal', action="public_journal_rss")
361
362 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % ADMIN_PREFIX,
346 controller='journal', action="public_journal_rss")
363 controller='journal', action="public_journal_rss")
347
364
348 rmap.connect('public_journal_atom',
365 rmap.connect('public_journal_atom',
366 '%s/public_journal/atom' % ADMIN_PREFIX, controller='journal',
367 action="public_journal_atom")
368
369 rmap.connect('public_journal_atom_old',
349 '%s/public_journal_atom' % ADMIN_PREFIX, controller='journal',
370 '%s/public_journal_atom' % ADMIN_PREFIX, controller='journal',
350 action="public_journal_atom")
371 action="public_journal_atom")
351
372
@@ -374,18 +395,18 b' def make_map(config):'
374 controller='login', action='password_reset_confirmation')
395 controller='login', action='password_reset_confirmation')
375
396
376 #FEEDS
397 #FEEDS
377 rmap.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
398 rmap.connect('rss_feed_home', '/{repo_name:.*?}/feed/rss',
378 controller='feed', action='rss',
399 controller='feed', action='rss',
379 conditions=dict(function=check_repo))
400 conditions=dict(function=check_repo))
380
401
381 rmap.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
402 rmap.connect('atom_feed_home', '/{repo_name:.*?}/feed/atom',
382 controller='feed', action='atom',
403 controller='feed', action='atom',
383 conditions=dict(function=check_repo))
404 conditions=dict(function=check_repo))
384
405
385 #==========================================================================
406 #==========================================================================
386 # REPOSITORY ROUTES
407 # REPOSITORY ROUTES
387 #==========================================================================
408 #==========================================================================
388 rmap.connect('summary_home', '/{repo_name:.*}',
409 rmap.connect('summary_home', '/{repo_name:.*?}',
389 controller='summary',
410 controller='summary',
390 conditions=dict(function=check_repo))
411 conditions=dict(function=check_repo))
391
412
@@ -393,114 +414,166 b' def make_map(config):'
393 controller='admin/repos_groups', action="show_by_name",
414 controller='admin/repos_groups', action="show_by_name",
394 conditions=dict(function=check_group))
415 conditions=dict(function=check_group))
395
416
396 rmap.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
417 rmap.connect('changeset_home', '/{repo_name:.*?}/changeset/{revision}',
397 controller='changeset', revision='tip',
418 controller='changeset', revision='tip',
398 conditions=dict(function=check_repo))
419 conditions=dict(function=check_repo))
399
420
400 rmap.connect('changeset_comment',
421 rmap.connect('changeset_comment',
401 '/{repo_name:.*}/changeset/{revision}/comment',
422 '/{repo_name:.*?}/changeset/{revision}/comment',
402 controller='changeset', revision='tip', action='comment',
423 controller='changeset', revision='tip', action='comment',
403 conditions=dict(function=check_repo))
424 conditions=dict(function=check_repo))
404
425
405 rmap.connect('changeset_comment_delete',
426 rmap.connect('changeset_comment_delete',
406 '/{repo_name:.*}/changeset/comment/{comment_id}/delete',
427 '/{repo_name:.*?}/changeset/comment/{comment_id}/delete',
407 controller='changeset', action='delete_comment',
428 controller='changeset', action='delete_comment',
408 conditions=dict(function=check_repo, method=["DELETE"]))
429 conditions=dict(function=check_repo, method=["DELETE"]))
409
430
410 rmap.connect('raw_changeset_home',
431 rmap.connect('raw_changeset_home',
411 '/{repo_name:.*}/raw-changeset/{revision}',
432 '/{repo_name:.*?}/raw-changeset/{revision}',
412 controller='changeset', action='raw_changeset',
433 controller='changeset', action='raw_changeset',
413 revision='tip', conditions=dict(function=check_repo))
434 revision='tip', conditions=dict(function=check_repo))
414
435
415 rmap.connect('summary_home', '/{repo_name:.*}/summary',
436 rmap.connect('compare_url',
437 '/{repo_name:.*?}/compare/{org_ref_type}@{org_ref}...{other_ref_type}@{other_ref}',
438 controller='compare', action='index',
439 conditions=dict(function=check_repo),
440 requirements=dict(
441 org_ref_type='(branch|book|tag|rev|org_ref_type)',
442 other_ref_type='(branch|book|tag|rev|other_ref_type)')
443 )
444
445 rmap.connect('pullrequest_home',
446 '/{repo_name:.*?}/pull-request/new', controller='pullrequests',
447 action='index', conditions=dict(function=check_repo,
448 method=["GET"]))
449
450 rmap.connect('pullrequest',
451 '/{repo_name:.*?}/pull-request/new', controller='pullrequests',
452 action='create', conditions=dict(function=check_repo,
453 method=["POST"]))
454
455 rmap.connect('pullrequest_show',
456 '/{repo_name:.*?}/pull-request/{pull_request_id}',
457 controller='pullrequests',
458 action='show', conditions=dict(function=check_repo,
459 method=["GET"]))
460 rmap.connect('pullrequest_update',
461 '/{repo_name:.*?}/pull-request/{pull_request_id}',
462 controller='pullrequests',
463 action='update', conditions=dict(function=check_repo,
464 method=["PUT"]))
465 rmap.connect('pullrequest_delete',
466 '/{repo_name:.*?}/pull-request/{pull_request_id}',
467 controller='pullrequests',
468 action='delete', conditions=dict(function=check_repo,
469 method=["DELETE"]))
470
471 rmap.connect('pullrequest_show_all',
472 '/{repo_name:.*?}/pull-request',
473 controller='pullrequests',
474 action='show_all', conditions=dict(function=check_repo,
475 method=["GET"]))
476
477 rmap.connect('pullrequest_comment',
478 '/{repo_name:.*?}/pull-request-comment/{pull_request_id}',
479 controller='pullrequests',
480 action='comment', conditions=dict(function=check_repo,
481 method=["POST"]))
482
483 rmap.connect('pullrequest_comment_delete',
484 '/{repo_name:.*?}/pull-request-comment/{comment_id}/delete',
485 controller='pullrequests', action='delete_comment',
486 conditions=dict(function=check_repo, method=["DELETE"]))
487
488 rmap.connect('summary_home', '/{repo_name:.*?}/summary',
416 controller='summary', conditions=dict(function=check_repo))
489 controller='summary', conditions=dict(function=check_repo))
417
490
418 rmap.connect('shortlog_home', '/{repo_name:.*}/shortlog',
491 rmap.connect('shortlog_home', '/{repo_name:.*?}/shortlog',
419 controller='shortlog', conditions=dict(function=check_repo))
492 controller='shortlog', conditions=dict(function=check_repo))
420
493
421 rmap.connect('branches_home', '/{repo_name:.*}/branches',
494 rmap.connect('branches_home', '/{repo_name:.*?}/branches',
422 controller='branches', conditions=dict(function=check_repo))
495 controller='branches', conditions=dict(function=check_repo))
423
496
424 rmap.connect('tags_home', '/{repo_name:.*}/tags',
497 rmap.connect('tags_home', '/{repo_name:.*?}/tags',
425 controller='tags', conditions=dict(function=check_repo))
498 controller='tags', conditions=dict(function=check_repo))
426
499
427 rmap.connect('bookmarks_home', '/{repo_name:.*}/bookmarks',
500 rmap.connect('bookmarks_home', '/{repo_name:.*?}/bookmarks',
428 controller='bookmarks', conditions=dict(function=check_repo))
501 controller='bookmarks', conditions=dict(function=check_repo))
429
502
430 rmap.connect('changelog_home', '/{repo_name:.*}/changelog',
503 rmap.connect('changelog_home', '/{repo_name:.*?}/changelog',
431 controller='changelog', conditions=dict(function=check_repo))
504 controller='changelog', conditions=dict(function=check_repo))
432
505
433 rmap.connect('changelog_details', '/{repo_name:.*}/changelog_details/{cs}',
506 rmap.connect('changelog_details', '/{repo_name:.*?}/changelog_details/{cs}',
434 controller='changelog', action='changelog_details',
507 controller='changelog', action='changelog_details',
435 conditions=dict(function=check_repo))
508 conditions=dict(function=check_repo))
436
509
437 rmap.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
510 rmap.connect('files_home', '/{repo_name:.*?}/files/{revision}/{f_path:.*}',
438 controller='files', revision='tip', f_path='',
511 controller='files', revision='tip', f_path='',
439 conditions=dict(function=check_repo))
512 conditions=dict(function=check_repo))
440
513
441 rmap.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
514 rmap.connect('files_diff_home', '/{repo_name:.*?}/diff/{f_path:.*}',
442 controller='files', action='diff', revision='tip', f_path='',
515 controller='files', action='diff', revision='tip', f_path='',
443 conditions=dict(function=check_repo))
516 conditions=dict(function=check_repo))
444
517
445 rmap.connect('files_rawfile_home',
518 rmap.connect('files_rawfile_home',
446 '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
519 '/{repo_name:.*?}/rawfile/{revision}/{f_path:.*}',
447 controller='files', action='rawfile', revision='tip',
520 controller='files', action='rawfile', revision='tip',
448 f_path='', conditions=dict(function=check_repo))
521 f_path='', conditions=dict(function=check_repo))
449
522
450 rmap.connect('files_raw_home',
523 rmap.connect('files_raw_home',
451 '/{repo_name:.*}/raw/{revision}/{f_path:.*}',
524 '/{repo_name:.*?}/raw/{revision}/{f_path:.*}',
452 controller='files', action='raw', revision='tip', f_path='',
525 controller='files', action='raw', revision='tip', f_path='',
453 conditions=dict(function=check_repo))
526 conditions=dict(function=check_repo))
454
527
455 rmap.connect('files_annotate_home',
528 rmap.connect('files_annotate_home',
456 '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
529 '/{repo_name:.*?}/annotate/{revision}/{f_path:.*}',
457 controller='files', action='index', revision='tip',
530 controller='files', action='index', revision='tip',
458 f_path='', annotate=True, conditions=dict(function=check_repo))
531 f_path='', annotate=True, conditions=dict(function=check_repo))
459
532
460 rmap.connect('files_edit_home',
533 rmap.connect('files_edit_home',
461 '/{repo_name:.*}/edit/{revision}/{f_path:.*}',
534 '/{repo_name:.*?}/edit/{revision}/{f_path:.*}',
462 controller='files', action='edit', revision='tip',
535 controller='files', action='edit', revision='tip',
463 f_path='', conditions=dict(function=check_repo))
536 f_path='', conditions=dict(function=check_repo))
464
537
465 rmap.connect('files_add_home',
538 rmap.connect('files_add_home',
466 '/{repo_name:.*}/add/{revision}/{f_path:.*}',
539 '/{repo_name:.*?}/add/{revision}/{f_path:.*}',
467 controller='files', action='add', revision='tip',
540 controller='files', action='add', revision='tip',
468 f_path='', conditions=dict(function=check_repo))
541 f_path='', conditions=dict(function=check_repo))
469
542
470 rmap.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}',
543 rmap.connect('files_archive_home', '/{repo_name:.*?}/archive/{fname}',
471 controller='files', action='archivefile',
544 controller='files', action='archivefile',
472 conditions=dict(function=check_repo))
545 conditions=dict(function=check_repo))
473
546
474 rmap.connect('files_nodelist_home',
547 rmap.connect('files_nodelist_home',
475 '/{repo_name:.*}/nodelist/{revision}/{f_path:.*}',
548 '/{repo_name:.*?}/nodelist/{revision}/{f_path:.*}',
476 controller='files', action='nodelist',
549 controller='files', action='nodelist',
477 conditions=dict(function=check_repo))
550 conditions=dict(function=check_repo))
478
551
479 rmap.connect('repo_settings_delete', '/{repo_name:.*}/settings',
552 rmap.connect('repo_settings_delete', '/{repo_name:.*?}/settings',
480 controller='settings', action="delete",
553 controller='settings', action="delete",
481 conditions=dict(method=["DELETE"], function=check_repo))
554 conditions=dict(method=["DELETE"], function=check_repo))
482
555
483 rmap.connect('repo_settings_update', '/{repo_name:.*}/settings',
556 rmap.connect('repo_settings_update', '/{repo_name:.*?}/settings',
484 controller='settings', action="update",
557 controller='settings', action="update",
485 conditions=dict(method=["PUT"], function=check_repo))
558 conditions=dict(method=["PUT"], function=check_repo))
486
559
487 rmap.connect('repo_settings_home', '/{repo_name:.*}/settings',
560 rmap.connect('repo_settings_home', '/{repo_name:.*?}/settings',
488 controller='settings', action='index',
561 controller='settings', action='index',
489 conditions=dict(function=check_repo))
562 conditions=dict(function=check_repo))
490
563
491 rmap.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
564 rmap.connect('repo_fork_create_home', '/{repo_name:.*?}/fork',
492 controller='forks', action='fork_create',
565 controller='forks', action='fork_create',
493 conditions=dict(function=check_repo, method=["POST"]))
566 conditions=dict(function=check_repo, method=["POST"]))
494
567
495 rmap.connect('repo_fork_home', '/{repo_name:.*}/fork',
568 rmap.connect('repo_fork_home', '/{repo_name:.*?}/fork',
496 controller='forks', action='fork',
569 controller='forks', action='fork',
497 conditions=dict(function=check_repo))
570 conditions=dict(function=check_repo))
498
571
499 rmap.connect('repo_forks_home', '/{repo_name:.*}/forks',
572 rmap.connect('repo_forks_home', '/{repo_name:.*?}/forks',
500 controller='forks', action='forks',
573 controller='forks', action='forks',
501 conditions=dict(function=check_repo))
574 conditions=dict(function=check_repo))
502
575
503 rmap.connect('repo_followers_home', '/{repo_name:.*}/followers',
576 rmap.connect('repo_followers_home', '/{repo_name:.*?}/followers',
504 controller='followers', action='followers',
577 controller='followers', action='followers',
505 conditions=dict(function=check_repo))
578 conditions=dict(function=check_repo))
506
579
@@ -45,7 +45,7 b' class AdminController(BaseController):'
45 @HasPermissionAllDecorator('hg.admin')
45 @HasPermissionAllDecorator('hg.admin')
46 def index(self):
46 def index(self):
47
47
48 users_log = self.sa.query(UserLog)\
48 users_log = UserLog.query()\
49 .options(joinedload(UserLog.user))\
49 .options(joinedload(UserLog.user))\
50 .options(joinedload(UserLog.repository))\
50 .options(joinedload(UserLog.repository))\
51 .order_by(UserLog.action_date.desc())
51 .order_by(UserLog.action_date.desc())
@@ -40,6 +40,7 b' from rhodecode.lib.auth import LoginRequ'
40 from rhodecode.lib.exceptions import LdapImportError
40 from rhodecode.lib.exceptions import LdapImportError
41 from rhodecode.model.forms import LdapSettingsForm
41 from rhodecode.model.forms import LdapSettingsForm
42 from rhodecode.model.db import RhodeCodeSetting
42 from rhodecode.model.db import RhodeCodeSetting
43 from rhodecode.model.meta import Session
43
44
44 log = logging.getLogger(__name__)
45 log = logging.getLogger(__name__)
45
46
@@ -119,9 +120,9 b' class LdapSettingsController(BaseControl'
119 v = ldap_active
120 v = ldap_active
120 setting = RhodeCodeSetting.get_by_name(k)
121 setting = RhodeCodeSetting.get_by_name(k)
121 setting.app_settings_value = v
122 setting.app_settings_value = v
122 self.sa.add(setting)
123 Session().add(setting)
123
124
124 self.sa.commit()
125 Session().commit()
125 h.flash(_('Ldap settings updated successfully'),
126 h.flash(_('Ldap settings updated successfully'),
126 category='success')
127 category='success')
127 if not ldap_active:
128 if not ldap_active:
@@ -60,19 +60,33 b' class NotificationsController(BaseContro'
60 """GET /_admin/notifications: All items in the collection"""
60 """GET /_admin/notifications: All items in the collection"""
61 # url('notifications')
61 # url('notifications')
62 c.user = self.rhodecode_user
62 c.user = self.rhodecode_user
63 notif = NotificationModel().get_for_user(self.rhodecode_user.user_id)
63 notif = NotificationModel().get_for_user(self.rhodecode_user.user_id,
64 filter_=request.GET.getall('type'))
64 p = int(request.params.get('page', 1))
65 p = int(request.params.get('page', 1))
65 c.notifications = Page(notif, page=p, items_per_page=10)
66 c.notifications = Page(notif, page=p, items_per_page=10)
67 c.pull_request_type = Notification.TYPE_PULL_REQUEST
68 c.comment_type = [Notification.TYPE_CHANGESET_COMMENT,
69 Notification.TYPE_PULL_REQUEST_COMMENT]
70
71 _current_filter = request.GET.getall('type')
72 c.current_filter = 'all'
73 if _current_filter == [c.pull_request_type]:
74 c.current_filter = 'pull_request'
75 elif _current_filter == c.comment_type:
76 c.current_filter = 'comment'
77
66 return render('admin/notifications/notifications.html')
78 return render('admin/notifications/notifications.html')
67
79
68 def mark_all_read(self):
80 def mark_all_read(self):
69 if request.environ.get('HTTP_X_PARTIAL_XHR'):
81 if request.environ.get('HTTP_X_PARTIAL_XHR'):
70 nm = NotificationModel()
82 nm = NotificationModel()
71 # mark all read
83 # mark all read
72 nm.mark_all_read_for_user(self.rhodecode_user.user_id)
84 nm.mark_all_read_for_user(self.rhodecode_user.user_id,
73 Session.commit()
85 filter_=request.GET.getall('type'))
86 Session().commit()
74 c.user = self.rhodecode_user
87 c.user = self.rhodecode_user
75 notif = nm.get_for_user(self.rhodecode_user.user_id)
88 notif = nm.get_for_user(self.rhodecode_user.user_id,
89 filter_=request.GET.getall('type'))
76 c.notifications = Page(notif, page=1, items_per_page=10)
90 c.notifications = Page(notif, page=1, items_per_page=10)
77 return render('admin/notifications/notifications_data.html')
91 return render('admin/notifications/notifications_data.html')
78
92
@@ -92,6 +106,18 b' class NotificationsController(BaseContro'
92 # h.form(url('notification', notification_id=ID),
106 # h.form(url('notification', notification_id=ID),
93 # method='put')
107 # method='put')
94 # url('notification', notification_id=ID)
108 # url('notification', notification_id=ID)
109 try:
110 no = Notification.get(notification_id)
111 owner = lambda: (no.notifications_to_users.user.user_id
112 == c.rhodecode_user.user_id)
113 if h.HasPermissionAny('hg.admin')() or owner:
114 NotificationModel().mark_read(c.rhodecode_user.user_id, no)
115 Session().commit()
116 return 'ok'
117 except Exception:
118 Session.rollback()
119 log.error(traceback.format_exc())
120 return 'fail'
95
121
96 def delete(self, notification_id):
122 def delete(self, notification_id):
97 """DELETE /_admin/notifications/id: Delete an existing item"""
123 """DELETE /_admin/notifications/id: Delete an existing item"""
@@ -106,9 +132,9 b' class NotificationsController(BaseContro'
106 no = Notification.get(notification_id)
132 no = Notification.get(notification_id)
107 owner = lambda: (no.notifications_to_users.user.user_id
133 owner = lambda: (no.notifications_to_users.user.user_id
108 == c.rhodecode_user.user_id)
134 == c.rhodecode_user.user_id)
109 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
135 if h.HasPermissionAny('hg.admin')() or owner:
110 NotificationModel().delete(c.rhodecode_user.user_id, no)
136 NotificationModel().delete(c.rhodecode_user.user_id, no)
111 Session.commit()
137 Session().commit()
112 return 'ok'
138 return 'ok'
113 except Exception:
139 except Exception:
114 Session.rollback()
140 Session.rollback()
@@ -132,7 +158,7 b' class NotificationsController(BaseContro'
132 if unotification:
158 if unotification:
133 if unotification.read is False:
159 if unotification.read is False:
134 unotification.mark_as_read()
160 unotification.mark_as_read()
135 Session.commit()
161 Session().commit()
136 c.notification = no
162 c.notification = no
137
163
138 return render('admin/notifications/show_notification.html')
164 return render('admin/notifications/show_notification.html')
@@ -71,6 +71,15 b' class PermissionsController(BaseControll'
71 self.create_choices = [('hg.create.none', _('Disabled')),
71 self.create_choices = [('hg.create.none', _('Disabled')),
72 ('hg.create.repository', _('Enabled'))]
72 ('hg.create.repository', _('Enabled'))]
73
73
74 self.fork_choices = [('hg.fork.none', _('Disabled')),
75 ('hg.fork.repository', _('Enabled'))]
76
77 # set the global template variables
78 c.perms_choices = self.perms_choices
79 c.register_choices = self.register_choices
80 c.create_choices = self.create_choices
81 c.fork_choices = self.fork_choices
82
74 def index(self, format='html'):
83 def index(self, format='html'):
75 """GET /permissions: All items in the collection"""
84 """GET /permissions: All items in the collection"""
76 # url('permissions')
85 # url('permissions')
@@ -96,20 +105,18 b' class PermissionsController(BaseControll'
96
105
97 _form = DefaultPermissionsForm([x[0] for x in self.perms_choices],
106 _form = DefaultPermissionsForm([x[0] for x in self.perms_choices],
98 [x[0] for x in self.register_choices],
107 [x[0] for x in self.register_choices],
99 [x[0] for x in self.create_choices])()
108 [x[0] for x in self.create_choices],
109 [x[0] for x in self.fork_choices])()
100
110
101 try:
111 try:
102 form_result = _form.to_python(dict(request.POST))
112 form_result = _form.to_python(dict(request.POST))
103 form_result.update({'perm_user_name': id})
113 form_result.update({'perm_user_name': id})
104 permission_model.update(form_result)
114 permission_model.update(form_result)
105 Session.commit()
115 Session().commit()
106 h.flash(_('Default permissions updated successfully'),
116 h.flash(_('Default permissions updated successfully'),
107 category='success')
117 category='success')
108
118
109 except formencode.Invalid, errors:
119 except formencode.Invalid, errors:
110 c.perms_choices = self.perms_choices
111 c.register_choices = self.register_choices
112 c.create_choices = self.create_choices
113 defaults = errors.value
120 defaults = errors.value
114
121
115 return htmlfill.render(
122 return htmlfill.render(
@@ -141,10 +148,8 b' class PermissionsController(BaseControll'
141 def edit(self, id, format='html'):
148 def edit(self, id, format='html'):
142 """GET /permissions/id/edit: Form to edit an existing item"""
149 """GET /permissions/id/edit: Form to edit an existing item"""
143 #url('edit_permission', id=ID)
150 #url('edit_permission', id=ID)
144 c.perms_choices = self.perms_choices
145 c.register_choices = self.register_choices
146 c.create_choices = self.create_choices
147
151
152 #this form can only edit default user permissions
148 if id == 'default':
153 if id == 'default':
149 default_user = User.get_by_username('default')
154 default_user = User.get_by_username('default')
150 defaults = {'_method': 'put',
155 defaults = {'_method': 'put',
@@ -160,10 +165,14 b' class PermissionsController(BaseControll'
160 if p.permission.permission_name.startswith('hg.create.'):
165 if p.permission.permission_name.startswith('hg.create.'):
161 defaults['default_create'] = p.permission.permission_name
166 defaults['default_create'] = p.permission.permission_name
162
167
168 if p.permission.permission_name.startswith('hg.fork.'):
169 defaults['default_fork'] = p.permission.permission_name
170
163 return htmlfill.render(
171 return htmlfill.render(
164 render('admin/permissions/permissions.html'),
172 render('admin/permissions/permissions.html'),
165 defaults=defaults,
173 defaults=defaults,
166 encoding="UTF-8",
174 encoding="UTF-8",
167 force_defaults=True,)
175 force_defaults=True,
176 )
168 else:
177 else:
169 return redirect(url('admin_home'))
178 return redirect(url('admin_home'))
@@ -28,12 +28,13 b' import traceback'
28 import formencode
28 import formencode
29 from formencode import htmlfill
29 from formencode import htmlfill
30
30
31 from paste.httpexceptions import HTTPInternalServerError
31 from webob.exc import HTTPInternalServerError
32 from pylons import request, session, tmpl_context as c, url
32 from pylons import request, session, tmpl_context as c, url
33 from pylons.controllers.util import redirect
33 from pylons.controllers.util import redirect
34 from pylons.i18n.translation import _
34 from pylons.i18n.translation import _
35 from sqlalchemy.exc import IntegrityError
35 from sqlalchemy.exc import IntegrityError
36
36
37 import rhodecode
37 from rhodecode.lib import helpers as h
38 from rhodecode.lib import helpers as h
38 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
39 HasPermissionAnyDecorator, HasRepoPermissionAllDecorator
40 HasPermissionAnyDecorator, HasRepoPermissionAllDecorator
@@ -45,6 +46,7 b' from rhodecode.model.db import User, Rep'
45 from rhodecode.model.forms import RepoForm
46 from rhodecode.model.forms import RepoForm
46 from rhodecode.model.scm import ScmModel
47 from rhodecode.model.scm import ScmModel
47 from rhodecode.model.repo import RepoModel
48 from rhodecode.model.repo import RepoModel
49 from rhodecode.lib.compat import json
48
50
49 log = logging.getLogger(__name__)
51 log = logging.getLogger(__name__)
50
52
@@ -70,6 +72,8 b' class ReposController(BaseController):'
70 repo_model = RepoModel()
72 repo_model = RepoModel()
71 c.users_array = repo_model.get_users_js()
73 c.users_array = repo_model.get_users_js()
72 c.users_groups_array = repo_model.get_users_groups_js()
74 c.users_groups_array = repo_model.get_users_groups_js()
75 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
76 c.landing_revs_choices = choices
73
77
74 def __load_data(self, repo_name=None):
78 def __load_data(self, repo_name=None):
75 """
79 """
@@ -91,6 +95,9 b' class ReposController(BaseController):'
91
95
92 return redirect(url('repos'))
96 return redirect(url('repos'))
93
97
98 choices, c.landing_revs = ScmModel().get_repo_landing_revs(c.repo_info)
99 c.landing_revs_choices = choices
100
94 c.default_user_id = User.get_by_username('default').user_id
101 c.default_user_id = User.get_by_username('default').user_id
95 c.in_public_journal = UserFollowing.query()\
102 c.in_public_journal = UserFollowing.query()\
96 .filter(UserFollowing.user_id == c.default_user_id)\
103 .filter(UserFollowing.user_id == c.default_user_id)\
@@ -115,7 +122,10 b' class ReposController(BaseController):'
115
122
116 c.repos_list = [('', _('--REMOVE FORK--'))]
123 c.repos_list = [('', _('--REMOVE FORK--'))]
117 c.repos_list += [(x.repo_id, x.repo_name) for x in
124 c.repos_list += [(x.repo_id, x.repo_name) for x in
118 Repository.query().order_by(Repository.repo_name).all()]
125 Repository.query().order_by(Repository.repo_name).all()
126 if x.repo_id != c.repo_info.repo_id]
127
128 defaults['id_fork_of'] = db_repo.fork.repo_id if db_repo.fork else ''
119 return defaults
129 return defaults
120
130
121 @HasPermissionAllDecorator('hg.admin')
131 @HasPermissionAllDecorator('hg.admin')
@@ -123,9 +133,45 b' class ReposController(BaseController):'
123 """GET /repos: All items in the collection"""
133 """GET /repos: All items in the collection"""
124 # url('repos')
134 # url('repos')
125
135
126 c.repos_list = ScmModel().get_repos(Repository.query()
136 c.repos_list = Repository.query()\
127 .order_by(Repository.repo_name)
137 .order_by(Repository.repo_name)\
128 .all(), sort_key='name_sort')
138 .all()
139
140 repos_data = []
141 total_records = len(c.repos_list)
142
143 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
144 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
145
146 quick_menu = lambda repo_name: (template.get_def("quick_menu")
147 .render(repo_name, _=_, h=h, c=c))
148 repo_lnk = lambda name, rtype, private, fork_of: (
149 template.get_def("repo_name")
150 .render(name, rtype, private, fork_of, short_name=False,
151 admin=True, _=_, h=h, c=c))
152
153 repo_actions = lambda repo_name: (template.get_def("repo_actions")
154 .render(repo_name, _=_, h=h, c=c))
155
156 for repo in c.repos_list:
157 repos_data.append({
158 "menu": quick_menu(repo.repo_name),
159 "raw_name": repo.repo_name,
160 "name": repo_lnk(repo.repo_name, repo.repo_type,
161 repo.private, repo.fork),
162 "desc": repo.description,
163 "owner": repo.user.username,
164 "action": repo_actions(repo.repo_name),
165 })
166
167 c.data = json.dumps({
168 "totalRecords": total_records,
169 "startIndex": 0,
170 "sort": "name",
171 "dir": "asc",
172 "records": repos_data
173 })
174
129 return render('admin/repos/repos.html')
175 return render('admin/repos/repos.html')
130
176
131 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
177 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
@@ -137,9 +183,11 b' class ReposController(BaseController):'
137 self.__load_defaults()
183 self.__load_defaults()
138 form_result = {}
184 form_result = {}
139 try:
185 try:
140 form_result = RepoForm(repo_groups=c.repo_groups_choices)()\
186 form_result = RepoForm(repo_groups=c.repo_groups_choices,
187 landing_revs=c.landing_revs_choices)()\
141 .to_python(dict(request.POST))
188 .to_python(dict(request.POST))
142 RepoModel().create(form_result, self.rhodecode_user)
189 new_repo = RepoModel().create(form_result,
190 self.rhodecode_user.user_id)
143 if form_result['clone_uri']:
191 if form_result['clone_uri']:
144 h.flash(_('created repository %s from %s') \
192 h.flash(_('created repository %s from %s') \
145 % (form_result['repo_name'], form_result['clone_uri']),
193 % (form_result['repo_name'], form_result['clone_uri']),
@@ -151,11 +199,13 b' class ReposController(BaseController):'
151 if request.POST.get('user_created'):
199 if request.POST.get('user_created'):
152 # created by regular non admin user
200 # created by regular non admin user
153 action_logger(self.rhodecode_user, 'user_created_repo',
201 action_logger(self.rhodecode_user, 'user_created_repo',
154 form_result['repo_name_full'], '', self.sa)
202 form_result['repo_name_full'], self.ip_addr,
203 self.sa)
155 else:
204 else:
156 action_logger(self.rhodecode_user, 'admin_created_repo',
205 action_logger(self.rhodecode_user, 'admin_created_repo',
157 form_result['repo_name_full'], '', self.sa)
206 form_result['repo_name_full'], self.ip_addr,
158 Session.commit()
207 self.sa)
208 Session().commit()
159 except formencode.Invalid, errors:
209 except formencode.Invalid, errors:
160
210
161 c.new_repo = errors.value['repo_name']
211 c.new_repo = errors.value['repo_name']
@@ -177,9 +227,9 b' class ReposController(BaseController):'
177 msg = _('error occurred during creation of repository %s') \
227 msg = _('error occurred during creation of repository %s') \
178 % form_result.get('repo_name')
228 % form_result.get('repo_name')
179 h.flash(msg, category='error')
229 h.flash(msg, category='error')
180 if request.POST.get('user_created'):
230 return redirect(url('repos'))
181 return redirect(url('home'))
231 #redirect to our new repo !
182 return redirect(url('repos'))
232 return redirect(url('summary_home', repo_name=new_repo.repo_name))
183
233
184 @HasPermissionAllDecorator('hg.admin')
234 @HasPermissionAllDecorator('hg.admin')
185 def new(self, format='html'):
235 def new(self, format='html'):
@@ -202,18 +252,23 b' class ReposController(BaseController):'
202 self.__load_defaults()
252 self.__load_defaults()
203 repo_model = RepoModel()
253 repo_model = RepoModel()
204 changed_name = repo_name
254 changed_name = repo_name
255 #override the choices with extracted revisions !
256 choices, c.landing_revs = ScmModel().get_repo_landing_revs(repo_name)
257 c.landing_revs_choices = choices
258
205 _form = RepoForm(edit=True, old_data={'repo_name': repo_name},
259 _form = RepoForm(edit=True, old_data={'repo_name': repo_name},
206 repo_groups=c.repo_groups_choices)()
260 repo_groups=c.repo_groups_choices,
261 landing_revs=c.landing_revs_choices)()
207 try:
262 try:
208 form_result = _form.to_python(dict(request.POST))
263 form_result = _form.to_python(dict(request.POST))
209 repo = repo_model.update(repo_name, form_result)
264 repo = repo_model.update(repo_name, form_result)
210 invalidate_cache('get_repo_cached_%s' % repo_name)
265 invalidate_cache('get_repo_cached_%s' % repo_name)
211 h.flash(_('Repository %s updated successfully' % repo_name),
266 h.flash(_('Repository %s updated successfully') % repo_name,
212 category='success')
267 category='success')
213 changed_name = repo.repo_name
268 changed_name = repo.repo_name
214 action_logger(self.rhodecode_user, 'admin_updated_repo',
269 action_logger(self.rhodecode_user, 'admin_updated_repo',
215 changed_name, '', self.sa)
270 changed_name, self.ip_addr, self.sa)
216 Session.commit()
271 Session().commit()
217 except formencode.Invalid, errors:
272 except formencode.Invalid, errors:
218 defaults = self.__load_data(repo_name)
273 defaults = self.__load_data(repo_name)
219 defaults.update(errors.value)
274 defaults.update(errors.value)
@@ -253,11 +308,11 b' class ReposController(BaseController):'
253 return redirect(url('repos'))
308 return redirect(url('repos'))
254 try:
309 try:
255 action_logger(self.rhodecode_user, 'admin_deleted_repo',
310 action_logger(self.rhodecode_user, 'admin_deleted_repo',
256 repo_name, '', self.sa)
311 repo_name, self.ip_addr, self.sa)
257 repo_model.delete(repo)
312 repo_model.delete(repo)
258 invalidate_cache('get_repo_cached_%s' % repo_name)
313 invalidate_cache('get_repo_cached_%s' % repo_name)
259 h.flash(_('deleted repository %s') % repo_name, category='success')
314 h.flash(_('deleted repository %s') % repo_name, category='success')
260 Session.commit()
315 Session().commit()
261 except IntegrityError, e:
316 except IntegrityError, e:
262 if e.message.find('repositories_fork_id_fkey') != -1:
317 if e.message.find('repositories_fork_id_fkey') != -1:
263 log.error(traceback.format_exc())
318 log.error(traceback.format_exc())
@@ -287,7 +342,7 b' class ReposController(BaseController):'
287 try:
342 try:
288 RepoModel().revoke_user_permission(repo=repo_name,
343 RepoModel().revoke_user_permission(repo=repo_name,
289 user=request.POST['user_id'])
344 user=request.POST['user_id'])
290 Session.commit()
345 Session().commit()
291 except Exception:
346 except Exception:
292 log.error(traceback.format_exc())
347 log.error(traceback.format_exc())
293 h.flash(_('An error occurred during deletion of repository user'),
348 h.flash(_('An error occurred during deletion of repository user'),
@@ -306,7 +361,7 b' class ReposController(BaseController):'
306 RepoModel().revoke_users_group_permission(
361 RepoModel().revoke_users_group_permission(
307 repo=repo_name, group_name=request.POST['users_group_id']
362 repo=repo_name, group_name=request.POST['users_group_id']
308 )
363 )
309 Session.commit()
364 Session().commit()
310 except Exception:
365 except Exception:
311 log.error(traceback.format_exc())
366 log.error(traceback.format_exc())
312 h.flash(_('An error occurred during deletion of repository'
367 h.flash(_('An error occurred during deletion of repository'
@@ -324,8 +379,9 b' class ReposController(BaseController):'
324
379
325 try:
380 try:
326 RepoModel().delete_stats(repo_name)
381 RepoModel().delete_stats(repo_name)
327 Session.commit()
382 Session().commit()
328 except Exception, e:
383 except Exception, e:
384 log.error(traceback.format_exc())
329 h.flash(_('An error occurred during deletion of repository stats'),
385 h.flash(_('An error occurred during deletion of repository stats'),
330 category='error')
386 category='error')
331 return redirect(url('edit_repo', repo_name=repo_name))
387 return redirect(url('edit_repo', repo_name=repo_name))
@@ -340,13 +396,34 b' class ReposController(BaseController):'
340
396
341 try:
397 try:
342 ScmModel().mark_for_invalidation(repo_name)
398 ScmModel().mark_for_invalidation(repo_name)
343 Session.commit()
399 Session().commit()
344 except Exception, e:
400 except Exception, e:
401 log.error(traceback.format_exc())
345 h.flash(_('An error occurred during cache invalidation'),
402 h.flash(_('An error occurred during cache invalidation'),
346 category='error')
403 category='error')
347 return redirect(url('edit_repo', repo_name=repo_name))
404 return redirect(url('edit_repo', repo_name=repo_name))
348
405
349 @HasPermissionAllDecorator('hg.admin')
406 @HasPermissionAllDecorator('hg.admin')
407 def repo_locking(self, repo_name):
408 """
409 Unlock repository when it is locked !
410
411 :param repo_name:
412 """
413
414 try:
415 repo = Repository.get_by_repo_name(repo_name)
416 if request.POST.get('set_lock'):
417 Repository.lock(repo, c.rhodecode_user.user_id)
418 elif request.POST.get('set_unlock'):
419 Repository.unlock(repo)
420 except Exception, e:
421 log.error(traceback.format_exc())
422 h.flash(_('An error occurred during unlocking'),
423 category='error')
424 return redirect(url('edit_repo', repo_name=repo_name))
425
426 @HasPermissionAllDecorator('hg.admin')
350 def repo_public_journal(self, repo_name):
427 def repo_public_journal(self, repo_name):
351 """
428 """
352 Set's this repository to be visible in public journal,
429 Set's this repository to be visible in public journal,
@@ -364,7 +441,7 b' class ReposController(BaseController):'
364 self.scm_model.toggle_following_repo(repo_id, user_id)
441 self.scm_model.toggle_following_repo(repo_id, user_id)
365 h.flash(_('Updated repository visibility in public journal'),
442 h.flash(_('Updated repository visibility in public journal'),
366 category='success')
443 category='success')
367 Session.commit()
444 Session().commit()
368 except:
445 except:
369 h.flash(_('An error occurred during setting this'
446 h.flash(_('An error occurred during setting this'
370 ' repository in public journal'),
447 ' repository in public journal'),
@@ -403,11 +480,11 b' class ReposController(BaseController):'
403 repo = ScmModel().mark_as_fork(repo_name, fork_id,
480 repo = ScmModel().mark_as_fork(repo_name, fork_id,
404 self.rhodecode_user.username)
481 self.rhodecode_user.username)
405 fork = repo.fork.repo_name if repo.fork else _('Nothing')
482 fork = repo.fork.repo_name if repo.fork else _('Nothing')
406 Session.commit()
483 Session().commit()
407 h.flash(_('Marked repo %s as fork of %s' % (repo_name,fork)),
484 h.flash(_('Marked repo %s as fork of %s') % (repo_name, fork),
408 category='success')
485 category='success')
409 except Exception, e:
486 except Exception, e:
410 raise
487 log.error(traceback.format_exc())
411 h.flash(_('An error occurred during this operation'),
488 h.flash(_('An error occurred during this operation'),
412 category='error')
489 category='error')
413
490
@@ -44,7 +44,7 b' from rhodecode.model.repos_group import '
44 from rhodecode.model.forms import ReposGroupForm
44 from rhodecode.model.forms import ReposGroupForm
45 from rhodecode.model.meta import Session
45 from rhodecode.model.meta import Session
46 from rhodecode.model.repo import RepoModel
46 from rhodecode.model.repo import RepoModel
47 from webob.exc import HTTPInternalServerError
47 from webob.exc import HTTPInternalServerError, HTTPNotFound
48
48
49 log = logging.getLogger(__name__)
49 log = logging.getLogger(__name__)
50
50
@@ -74,11 +74,8 b' class ReposGroupsController(BaseControll'
74 :param group_id:
74 :param group_id:
75 """
75 """
76 self.__load_defaults()
76 self.__load_defaults()
77
77 repo_group = RepoGroup.get_or_404(group_id)
78 repo_group = RepoGroup.get(group_id)
79
80 data = repo_group.get_dict()
78 data = repo_group.get_dict()
81
82 data['group_name'] = repo_group.name
79 data['group_name'] = repo_group.name
83
80
84 # fill repository users
81 # fill repository users
@@ -115,7 +112,7 b' class ReposGroupsController(BaseControll'
115 group_description=form_result['group_description'],
112 group_description=form_result['group_description'],
116 parent=form_result['group_parent_id']
113 parent=form_result['group_parent_id']
117 )
114 )
118 Session.commit()
115 Session().commit()
119 h.flash(_('created repos group %s') \
116 h.flash(_('created repos group %s') \
120 % form_result['group_name'], category='success')
117 % form_result['group_name'], category='success')
121 #TODO: in futureaction_logger(, '', '', '', self.sa)
118 #TODO: in futureaction_logger(, '', '', '', self.sa)
@@ -162,7 +159,7 b' class ReposGroupsController(BaseControll'
162 try:
159 try:
163 form_result = repos_group_form.to_python(dict(request.POST))
160 form_result = repos_group_form.to_python(dict(request.POST))
164 ReposGroupModel().update(id, form_result)
161 ReposGroupModel().update(id, form_result)
165 Session.commit()
162 Session().commit()
166 h.flash(_('updated repos group %s') \
163 h.flash(_('updated repos group %s') \
167 % form_result['group_name'], category='success')
164 % form_result['group_name'], category='success')
168 #TODO: in futureaction_logger(, '', '', '', self.sa)
165 #TODO: in futureaction_logger(, '', '', '', self.sa)
@@ -179,7 +176,7 b' class ReposGroupsController(BaseControll'
179 h.flash(_('error occurred during update of repos group %s') \
176 h.flash(_('error occurred during update of repos group %s') \
180 % request.POST.get('group_name'), category='error')
177 % request.POST.get('group_name'), category='error')
181
178
182 return redirect(url('repos_groups'))
179 return redirect(url('edit_repos_group', id=id))
183
180
184 @HasPermissionAnyDecorator('hg.admin')
181 @HasPermissionAnyDecorator('hg.admin')
185 def delete(self, id):
182 def delete(self, id):
@@ -195,17 +192,18 b' class ReposGroupsController(BaseControll'
195 repos = gr.repositories.all()
192 repos = gr.repositories.all()
196 if repos:
193 if repos:
197 h.flash(_('This group contains %s repositores and cannot be '
194 h.flash(_('This group contains %s repositores and cannot be '
198 'deleted' % len(repos)),
195 'deleted') % len(repos),
199 category='error')
196 category='error')
200 return redirect(url('repos_groups'))
197 return redirect(url('repos_groups'))
201
198
202 try:
199 try:
203 ReposGroupModel().delete(id)
200 ReposGroupModel().delete(id)
204 Session.commit()
201 Session().commit()
205 h.flash(_('removed repos group %s' % gr.group_name), category='success')
202 h.flash(_('removed repos group %s') % gr.group_name,
203 category='success')
206 #TODO: in future action_logger(, '', '', '', self.sa)
204 #TODO: in future action_logger(, '', '', '', self.sa)
207 except IntegrityError, e:
205 except IntegrityError, e:
208 if e.message.find('groups_group_parent_id_fkey') != -1:
206 if str(e.message).find('groups_group_parent_id_fkey') != -1:
209 log.error(traceback.format_exc())
207 log.error(traceback.format_exc())
210 h.flash(_('Cannot delete this group it still contains '
208 h.flash(_('Cannot delete this group it still contains '
211 'subgroups'),
209 'subgroups'),
@@ -213,12 +211,12 b' class ReposGroupsController(BaseControll'
213 else:
211 else:
214 log.error(traceback.format_exc())
212 log.error(traceback.format_exc())
215 h.flash(_('error occurred during deletion of repos '
213 h.flash(_('error occurred during deletion of repos '
216 'group %s' % gr.group_name), category='error')
214 'group %s') % gr.group_name, category='error')
217
215
218 except Exception:
216 except Exception:
219 log.error(traceback.format_exc())
217 log.error(traceback.format_exc())
220 h.flash(_('error occurred during deletion of repos '
218 h.flash(_('error occurred during deletion of repos '
221 'group %s' % gr.group_name), category='error')
219 'group %s') % gr.group_name, category='error')
222
220
223 return redirect(url('repos_groups'))
221 return redirect(url('repos_groups'))
224
222
@@ -234,7 +232,7 b' class ReposGroupsController(BaseControll'
234 ReposGroupModel().revoke_user_permission(
232 ReposGroupModel().revoke_user_permission(
235 repos_group=group_name, user=request.POST['user_id']
233 repos_group=group_name, user=request.POST['user_id']
236 )
234 )
237 Session.commit()
235 Session().commit()
238 except Exception:
236 except Exception:
239 log.error(traceback.format_exc())
237 log.error(traceback.format_exc())
240 h.flash(_('An error occurred during deletion of group user'),
238 h.flash(_('An error occurred during deletion of group user'),
@@ -254,7 +252,7 b' class ReposGroupsController(BaseControll'
254 repos_group=group_name,
252 repos_group=group_name,
255 group_name=request.POST['users_group_id']
253 group_name=request.POST['users_group_id']
256 )
254 )
257 Session.commit()
255 Session().commit()
258 except Exception:
256 except Exception:
259 log.error(traceback.format_exc())
257 log.error(traceback.format_exc())
260 h.flash(_('An error occurred during deletion of group'
258 h.flash(_('An error occurred during deletion of group'
@@ -268,8 +266,10 b' class ReposGroupsController(BaseControll'
268 the group by id view instead
266 the group by id view instead
269 """
267 """
270 group_name = group_name.rstrip('/')
268 group_name = group_name.rstrip('/')
271 id_ = RepoGroup.get_by_group_name(group_name).group_id
269 id_ = RepoGroup.get_by_group_name(group_name)
272 return self.show(id_)
270 if id_:
271 return self.show(id_.group_id)
272 raise HTTPNotFound
273
273
274 @HasReposGroupPermissionAnyDecorator('group.read', 'group.write',
274 @HasReposGroupPermissionAnyDecorator('group.read', 'group.write',
275 'group.admin')
275 'group.admin')
@@ -277,12 +277,9 b' class ReposGroupsController(BaseControll'
277 """GET /repos_groups/id: Show a specific item"""
277 """GET /repos_groups/id: Show a specific item"""
278 # url('repos_group', id=ID)
278 # url('repos_group', id=ID)
279
279
280 c.group = RepoGroup.get(id)
280 c.group = RepoGroup.get_or_404(id)
281
281
282 if c.group:
282 c.group_repos = c.group.repositories.all()
283 c.group_repos = c.group.repositories.all()
284 else:
285 return redirect(url('home'))
286
283
287 #overwrite our cached list with current filter
284 #overwrite our cached list with current filter
288 gr_filter = c.group_repos
285 gr_filter = c.group_repos
@@ -292,7 +289,7 b' class ReposGroupsController(BaseControll'
292
289
293 c.repo_cnt = 0
290 c.repo_cnt = 0
294
291
295 c.groups = self.sa.query(RepoGroup).order_by(RepoGroup.group_name)\
292 c.groups = RepoGroup.query().order_by(RepoGroup.group_name)\
296 .filter(RepoGroup.group_parent_id == id).all()
293 .filter(RepoGroup.group_parent_id == id).all()
297
294
298 return render('admin/repos_groups/repos_groups.html')
295 return render('admin/repos_groups/repos_groups.html')
@@ -302,13 +299,12 b' class ReposGroupsController(BaseControll'
302 """GET /repos_groups/id/edit: Form to edit an existing item"""
299 """GET /repos_groups/id/edit: Form to edit an existing item"""
303 # url('edit_repos_group', id=ID)
300 # url('edit_repos_group', id=ID)
304
301
305 id_ = int(id)
302 c.repos_group = ReposGroupModel()._get_repos_group(id)
306
303 defaults = self.__load_data(c.repos_group.group_id)
307 c.repos_group = RepoGroup.get(id_)
308 defaults = self.__load_data(id_)
309
304
310 # we need to exclude this group from the group list for editing
305 # we need to exclude this group from the group list for editing
311 c.repo_groups = filter(lambda x: x[0] != id_, c.repo_groups)
306 c.repo_groups = filter(lambda x: x[0] != c.repos_group.group_id,
307 c.repo_groups)
312
308
313 return htmlfill.render(
309 return htmlfill.render(
314 render('admin/repos_groups/repos_groups_edit.html'),
310 render('admin/repos_groups/repos_groups_edit.html'),
@@ -43,9 +43,9 b' from rhodecode.lib.celerylib import task'
43 from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
43 from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
44 set_rhodecode_config, repo_name_slug
44 set_rhodecode_config, repo_name_slug
45 from rhodecode.model.db import RhodeCodeUi, Repository, RepoGroup, \
45 from rhodecode.model.db import RhodeCodeUi, Repository, RepoGroup, \
46 RhodeCodeSetting
46 RhodeCodeSetting, PullRequest, PullRequestReviewers
47 from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
47 from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
48 ApplicationUiSettingsForm
48 ApplicationUiSettingsForm, ApplicationVisualisationForm
49 from rhodecode.model.scm import ScmModel
49 from rhodecode.model.scm import ScmModel
50 from rhodecode.model.user import UserModel
50 from rhodecode.model.user import UserModel
51 from rhodecode.model.db import User
51 from rhodecode.model.db import User
@@ -79,7 +79,7 b' class SettingsController(BaseController)'
79 # url('admin_settings')
79 # url('admin_settings')
80
80
81 defaults = RhodeCodeSetting.get_app_settings()
81 defaults = RhodeCodeSetting.get_app_settings()
82 defaults.update(self.get_hg_ui_settings())
82 defaults.update(self._get_hg_ui_settings())
83
83
84 return htmlfill.render(
84 return htmlfill.render(
85 render('admin/settings/settings.html'),
85 render('admin/settings/settings.html'),
@@ -107,6 +107,7 b' class SettingsController(BaseController)'
107 # h.form(url('admin_setting', setting_id=ID),
107 # h.form(url('admin_setting', setting_id=ID),
108 # method='put')
108 # method='put')
109 # url('admin_setting', setting_id=ID)
109 # url('admin_setting', setting_id=ID)
110
110 if setting_id == 'mapping':
111 if setting_id == 'mapping':
111 rm_obsolete = request.POST.get('destroy', False)
112 rm_obsolete = request.POST.get('destroy', False)
112 log.debug('Rescanning directories with destroy=%s' % rm_obsolete)
113 log.debug('Rescanning directories with destroy=%s' % rm_obsolete)
@@ -119,122 +120,160 b' class SettingsController(BaseController)'
119
120
120 h.flash(_('Repositories successfully'
121 h.flash(_('Repositories successfully'
121 ' rescanned added: %s,removed: %s') % (added, removed),
122 ' rescanned added: %s,removed: %s') % (added, removed),
122 category='success')
123 category='success')
123
124
124 if setting_id == 'whoosh':
125 if setting_id == 'whoosh':
125 repo_location = self.get_hg_ui_settings()['paths_root_path']
126 repo_location = self._get_hg_ui_settings()['paths_root_path']
126 full_index = request.POST.get('full_index', False)
127 full_index = request.POST.get('full_index', False)
127 run_task(tasks.whoosh_index, repo_location, full_index)
128 run_task(tasks.whoosh_index, repo_location, full_index)
129 h.flash(_('Whoosh reindex task scheduled'), category='success')
128
130
129 h.flash(_('Whoosh reindex task scheduled'), category='success')
130 if setting_id == 'global':
131 if setting_id == 'global':
131
132
132 application_form = ApplicationSettingsForm()()
133 application_form = ApplicationSettingsForm()()
133 try:
134 try:
134 form_result = application_form.to_python(dict(request.POST))
135 form_result = application_form.to_python(dict(request.POST))
135
136 except formencode.Invalid, errors:
136 try:
137 return htmlfill.render(
137 hgsettings1 = RhodeCodeSetting.get_by_name('title')
138 render('admin/settings/settings.html'),
138 hgsettings1.app_settings_value = \
139 defaults=errors.value,
139 form_result['rhodecode_title']
140 errors=errors.error_dict or {},
141 prefix_error=False,
142 encoding="UTF-8"
143 )
140
144
141 hgsettings2 = RhodeCodeSetting.get_by_name('realm')
145 try:
142 hgsettings2.app_settings_value = \
146 sett1 = RhodeCodeSetting.get_by_name_or_create('title')
143 form_result['rhodecode_realm']
147 sett1.app_settings_value = form_result['rhodecode_title']
148 Session().add(sett1)
144
149
145 hgsettings3 = RhodeCodeSetting.get_by_name('ga_code')
150 sett2 = RhodeCodeSetting.get_by_name_or_create('realm')
146 hgsettings3.app_settings_value = \
151 sett2.app_settings_value = form_result['rhodecode_realm']
147 form_result['rhodecode_ga_code']
152 Session().add(sett2)
148
153
149 self.sa.add(hgsettings1)
154 sett3 = RhodeCodeSetting.get_by_name_or_create('ga_code')
150 self.sa.add(hgsettings2)
155 sett3.app_settings_value = form_result['rhodecode_ga_code']
151 self.sa.add(hgsettings3)
156 Session().add(sett3)
152 self.sa.commit()
157
153 set_rhodecode_config(config)
158 Session().commit()
154 h.flash(_('Updated application settings'),
159 set_rhodecode_config(config)
155 category='success')
160 h.flash(_('Updated application settings'), category='success')
156
161
157 except Exception:
162 except Exception:
158 log.error(traceback.format_exc())
163 log.error(traceback.format_exc())
159 h.flash(_('error occurred during updating '
164 h.flash(_('error occurred during updating '
160 'application settings'),
165 'application settings'),
161 category='error')
166 category='error')
162
167
163 self.sa.rollback()
168 if setting_id == 'visual':
164
169
170 application_form = ApplicationVisualisationForm()()
171 try:
172 form_result = application_form.to_python(dict(request.POST))
165 except formencode.Invalid, errors:
173 except formencode.Invalid, errors:
166 return htmlfill.render(
174 return htmlfill.render(
167 render('admin/settings/settings.html'),
175 render('admin/settings/settings.html'),
168 defaults=errors.value,
176 defaults=errors.value,
169 errors=errors.error_dict or {},
177 errors=errors.error_dict or {},
170 prefix_error=False,
178 prefix_error=False,
171 encoding="UTF-8")
179 encoding="UTF-8"
180 )
181
182 try:
183 sett1 = RhodeCodeSetting.get_by_name_or_create('show_public_icon')
184 sett1.app_settings_value = \
185 form_result['rhodecode_show_public_icon']
186
187 sett2 = RhodeCodeSetting.get_by_name_or_create('show_private_icon')
188 sett2.app_settings_value = \
189 form_result['rhodecode_show_private_icon']
190
191 sett3 = RhodeCodeSetting.get_by_name_or_create('stylify_metatags')
192 sett3.app_settings_value = \
193 form_result['rhodecode_stylify_metatags']
172
194
173 if setting_id == 'mercurial':
195 Session().add(sett1)
196 Session().add(sett2)
197 Session().add(sett3)
198 Session().commit()
199 set_rhodecode_config(config)
200 h.flash(_('Updated visualisation settings'),
201 category='success')
202
203 except Exception:
204 log.error(traceback.format_exc())
205 h.flash(_('error occurred during updating '
206 'visualisation settings'),
207 category='error')
208
209 if setting_id == 'vcs':
174 application_form = ApplicationUiSettingsForm()()
210 application_form = ApplicationUiSettingsForm()()
175 try:
211 try:
176 form_result = application_form.to_python(dict(request.POST))
212 form_result = application_form.to_python(dict(request.POST))
177
178 try:
179
180 hgsettings1 = self.sa.query(RhodeCodeUi)\
181 .filter(RhodeCodeUi.ui_key == 'push_ssl').one()
182 hgsettings1.ui_value = form_result['web_push_ssl']
183
184 hgsettings2 = self.sa.query(RhodeCodeUi)\
185 .filter(RhodeCodeUi.ui_key == '/').one()
186 hgsettings2.ui_value = form_result['paths_root_path']
187
188 #HOOKS
189 hgsettings3 = self.sa.query(RhodeCodeUi)\
190 .filter(RhodeCodeUi.ui_key == 'changegroup.update').one()
191 hgsettings3.ui_active = \
192 bool(form_result['hooks_changegroup_update'])
193
194 hgsettings4 = self.sa.query(RhodeCodeUi)\
195 .filter(RhodeCodeUi.ui_key ==
196 'changegroup.repo_size').one()
197 hgsettings4.ui_active = \
198 bool(form_result['hooks_changegroup_repo_size'])
199
200 hgsettings5 = self.sa.query(RhodeCodeUi)\
201 .filter(RhodeCodeUi.ui_key ==
202 'pretxnchangegroup.push_logger').one()
203 hgsettings5.ui_active = \
204 bool(form_result['hooks_pretxnchangegroup'
205 '_push_logger'])
206
207 hgsettings6 = self.sa.query(RhodeCodeUi)\
208 .filter(RhodeCodeUi.ui_key ==
209 'preoutgoing.pull_logger').one()
210 hgsettings6.ui_active = \
211 bool(form_result['hooks_preoutgoing_pull_logger'])
212
213 self.sa.add(hgsettings1)
214 self.sa.add(hgsettings2)
215 self.sa.add(hgsettings3)
216 self.sa.add(hgsettings4)
217 self.sa.add(hgsettings5)
218 self.sa.add(hgsettings6)
219 self.sa.commit()
220
221 h.flash(_('Updated mercurial settings'),
222 category='success')
223
224 except:
225 log.error(traceback.format_exc())
226 h.flash(_('error occurred during updating '
227 'application settings'), category='error')
228
229 self.sa.rollback()
230
231 except formencode.Invalid, errors:
213 except formencode.Invalid, errors:
232 return htmlfill.render(
214 return htmlfill.render(
233 render('admin/settings/settings.html'),
215 render('admin/settings/settings.html'),
234 defaults=errors.value,
216 defaults=errors.value,
235 errors=errors.error_dict or {},
217 errors=errors.error_dict or {},
236 prefix_error=False,
218 prefix_error=False,
237 encoding="UTF-8")
219 encoding="UTF-8"
220 )
221
222 try:
223 # fix namespaces for hooks and extensions
224 _f = lambda s: s.replace('.', '_')
225
226 sett = RhodeCodeUi.get_by_key('push_ssl')
227 sett.ui_value = form_result['web_push_ssl']
228 Session().add(sett)
229
230 sett = RhodeCodeUi.get_by_key('/')
231 sett.ui_value = form_result['paths_root_path']
232 Session().add(sett)
233
234 #HOOKS
235 sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_UPDATE)
236 sett.ui_active = form_result[_f('hooks_%s' %
237 RhodeCodeUi.HOOK_UPDATE)]
238 Session().add(sett)
239
240 sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_REPO_SIZE)
241 sett.ui_active = form_result[_f('hooks_%s' %
242 RhodeCodeUi.HOOK_REPO_SIZE)]
243 Session().add(sett)
244
245 sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_PUSH)
246 sett.ui_active = form_result[_f('hooks_%s' %
247 RhodeCodeUi.HOOK_PUSH)]
248 Session().add(sett)
249
250 sett = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_PULL)
251 sett.ui_active = form_result[_f('hooks_%s' %
252 RhodeCodeUi.HOOK_PULL)]
253
254 Session().add(sett)
255
256 ## EXTENSIONS
257 sett = RhodeCodeUi.get_by_key('largefiles')
258 sett.ui_active = form_result[_f('extensions_largefiles')]
259 Session().add(sett)
260
261 sett = RhodeCodeUi.get_by_key('hgsubversion')
262 sett.ui_active = form_result[_f('extensions_hgsubversion')]
263 Session().add(sett)
264
265 # sett = RhodeCodeUi.get_by_key('hggit')
266 # sett.ui_active = form_result[_f('extensions_hggit')]
267 # Session().add(sett)
268
269 Session().commit()
270
271 h.flash(_('Updated VCS settings'), category='success')
272
273 except Exception:
274 log.error(traceback.format_exc())
275 h.flash(_('error occurred during updating '
276 'application settings'), category='error')
238
277
239 if setting_id == 'hooks':
278 if setting_id == 'hooks':
240 ui_key = request.POST.get('new_hook_ui_key')
279 ui_key = request.POST.get('new_hook_ui_key')
@@ -256,8 +295,8 b' class SettingsController(BaseController)'
256
295
257 if update:
296 if update:
258 h.flash(_('Updated hooks'), category='success')
297 h.flash(_('Updated hooks'), category='success')
259 self.sa.commit()
298 Session().commit()
260 except:
299 except Exception:
261 log.error(traceback.format_exc())
300 log.error(traceback.format_exc())
262 h.flash(_('error occurred during hook creation'),
301 h.flash(_('error occurred during hook creation'),
263 category='error')
302 category='error')
@@ -293,7 +332,7 b' class SettingsController(BaseController)'
293 if setting_id == 'hooks':
332 if setting_id == 'hooks':
294 hook_id = request.POST.get('hook_id')
333 hook_id = request.POST.get('hook_id')
295 RhodeCodeUi.delete(hook_id)
334 RhodeCodeUi.delete(hook_id)
296 self.sa.commit()
335 Session().commit()
297
336
298 @HasPermissionAllDecorator('hg.admin')
337 @HasPermissionAllDecorator('hg.admin')
299 def show(self, setting_id, format='html'):
338 def show(self, setting_id, format='html'):
@@ -326,7 +365,7 b' class SettingsController(BaseController)'
326 # url('admin_settings_my_account')
365 # url('admin_settings_my_account')
327
366
328 c.user = User.get(self.rhodecode_user.user_id)
367 c.user = User.get(self.rhodecode_user.user_id)
329 all_repos = self.sa.query(Repository)\
368 all_repos = Session().query(Repository)\
330 .filter(Repository.user_id == c.user.user_id)\
369 .filter(Repository.user_id == c.user.user_id)\
331 .order_by(func.lower(Repository.repo_name)).all()
370 .order_by(func.lower(Repository.repo_name)).all()
332
371
@@ -338,13 +377,16 b' class SettingsController(BaseController)'
338 return redirect(url('users'))
377 return redirect(url('users'))
339
378
340 defaults = c.user.get_dict()
379 defaults = c.user.get_dict()
341 return htmlfill.render(
380
342 render('admin/users/user_edit_my_account.html'),
381 c.form = htmlfill.render(
382 render('admin/users/user_edit_my_account_form.html'),
343 defaults=defaults,
383 defaults=defaults,
344 encoding="UTF-8",
384 encoding="UTF-8",
345 force_defaults=False
385 force_defaults=False
346 )
386 )
387 return render('admin/users/user_edit_my_account.html')
347
388
389 @NotAnonymous()
348 def my_account_update(self):
390 def my_account_update(self):
349 """PUT /_admin/my_account_update: Update an existing item"""
391 """PUT /_admin/my_account_update: Update an existing item"""
350 # Forms posted to this method should contain a hidden field:
392 # Forms posted to this method should contain a hidden field:
@@ -353,32 +395,27 b' class SettingsController(BaseController)'
353 # h.form(url('admin_settings_my_account_update'),
395 # h.form(url('admin_settings_my_account_update'),
354 # method='put')
396 # method='put')
355 # url('admin_settings_my_account_update', id=ID)
397 # url('admin_settings_my_account_update', id=ID)
356 user_model = UserModel()
357 uid = self.rhodecode_user.user_id
398 uid = self.rhodecode_user.user_id
399 email = self.rhodecode_user.email
358 _form = UserForm(edit=True,
400 _form = UserForm(edit=True,
359 old_data={'user_id': uid,
401 old_data={'user_id': uid, 'email': email})()
360 'email': self.rhodecode_user.email})()
361 form_result = {}
402 form_result = {}
362 try:
403 try:
363 form_result = _form.to_python(dict(request.POST))
404 form_result = _form.to_python(dict(request.POST))
364 user_model.update_my_account(uid, form_result)
405 UserModel().update_my_account(uid, form_result)
365 h.flash(_('Your account was updated successfully'),
406 h.flash(_('Your account was updated successfully'),
366 category='success')
407 category='success')
367 Session.commit()
408 Session().commit()
368 except formencode.Invalid, errors:
409 except formencode.Invalid, errors:
369 c.user = User.get(self.rhodecode_user.user_id)
410 c.user = User.get(self.rhodecode_user.user_id)
370 all_repos = self.sa.query(Repository)\
371 .filter(Repository.user_id == c.user.user_id)\
372 .order_by(func.lower(Repository.repo_name))\
373 .all()
374 c.user_repos = ScmModel().get_repos(all_repos)
375
411
376 return htmlfill.render(
412 c.form = htmlfill.render(
377 render('admin/users/user_edit_my_account.html'),
413 render('admin/users/user_edit_my_account_form.html'),
378 defaults=errors.value,
414 defaults=errors.value,
379 errors=errors.error_dict or {},
415 errors=errors.error_dict or {},
380 prefix_error=False,
416 prefix_error=False,
381 encoding="UTF-8")
417 encoding="UTF-8")
418 return render('admin/users/user_edit_my_account.html')
382 except Exception:
419 except Exception:
383 log.error(traceback.format_exc())
420 log.error(traceback.format_exc())
384 h.flash(_('error occurred during update of user %s') \
421 h.flash(_('error occurred during update of user %s') \
@@ -387,20 +424,43 b' class SettingsController(BaseController)'
387 return redirect(url('my_account'))
424 return redirect(url('my_account'))
388
425
389 @NotAnonymous()
426 @NotAnonymous()
427 def my_account_my_repos(self):
428 all_repos = Session().query(Repository)\
429 .filter(Repository.user_id == self.rhodecode_user.user_id)\
430 .order_by(func.lower(Repository.repo_name))\
431 .all()
432 c.user_repos = ScmModel().get_repos(all_repos)
433 return render('admin/users/user_edit_my_account_repos.html')
434
435 @NotAnonymous()
436 def my_account_my_pullrequests(self):
437 c.my_pull_requests = PullRequest.query()\
438 .filter(PullRequest.user_id==
439 self.rhodecode_user.user_id)\
440 .all()
441 c.participate_in_pull_requests = \
442 [x.pull_request for x in PullRequestReviewers.query()\
443 .filter(PullRequestReviewers.user_id==
444 self.rhodecode_user.user_id)\
445 .all()]
446 return render('admin/users/user_edit_my_account_pullrequests.html')
447
448 @NotAnonymous()
390 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
449 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
391 def create_repository(self):
450 def create_repository(self):
392 """GET /_admin/create_repository: Form to create a new item"""
451 """GET /_admin/create_repository: Form to create a new item"""
393
452
394 c.repo_groups = RepoGroup.groups_choices()
453 c.repo_groups = RepoGroup.groups_choices()
395 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
454 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
455 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
396
456
397 new_repo = request.GET.get('repo', '')
457 new_repo = request.GET.get('repo', '')
398 c.new_repo = repo_name_slug(new_repo)
458 c.new_repo = repo_name_slug(new_repo)
399
459
400 return render('admin/repos/repo_add_create_repository.html')
460 return render('admin/repos/repo_add_create_repository.html')
401
461
402 def get_hg_ui_settings(self):
462 def _get_hg_ui_settings(self):
403 ret = self.sa.query(RhodeCodeUi).all()
463 ret = RhodeCodeUi.query().all()
404
464
405 if not ret:
465 if not ret:
406 raise Exception('Could not get application ui settings !')
466 raise Exception('Could not get application ui settings !')
@@ -414,7 +474,7 b' class SettingsController(BaseController)'
414 if k.find('.') != -1:
474 if k.find('.') != -1:
415 k = k.replace('.', '_')
475 k = k.replace('.', '_')
416
476
417 if each.ui_section == 'hooks':
477 if each.ui_section in ['hooks', 'extensions']:
418 v = each.ui_active
478 v = each.ui_active
419
479
420 settings[each.ui_section + '_' + k] = v
480 settings[each.ui_section + '_' + k] = v
@@ -26,22 +26,28 b''
26 import logging
26 import logging
27 import traceback
27 import traceback
28 import formencode
28 import formencode
29 from pylons import response
29
30
30 from formencode import htmlfill
31 from formencode import htmlfill
31 from pylons import request, session, tmpl_context as c, url, config
32 from pylons import request, session, tmpl_context as c, url, config
32 from pylons.controllers.util import redirect
33 from pylons.controllers.util import redirect
33 from pylons.i18n.translation import _
34 from pylons.i18n.translation import _
34
35
36 import rhodecode
35 from rhodecode.lib.exceptions import DefaultUserException, \
37 from rhodecode.lib.exceptions import DefaultUserException, \
36 UserOwnsReposException
38 UserOwnsReposException
37 from rhodecode.lib import helpers as h
39 from rhodecode.lib import helpers as h
38 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
40 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
41 AuthUser
39 from rhodecode.lib.base import BaseController, render
42 from rhodecode.lib.base import BaseController, render
40
43
41 from rhodecode.model.db import User, Permission
44 from rhodecode.model.db import User, UserEmailMap
42 from rhodecode.model.forms import UserForm
45 from rhodecode.model.forms import UserForm
43 from rhodecode.model.user import UserModel
46 from rhodecode.model.user import UserModel
44 from rhodecode.model.meta import Session
47 from rhodecode.model.meta import Session
48 from rhodecode.lib.utils import action_logger
49 from rhodecode.lib.compat import json
50 from rhodecode.lib.utils2 import datetime_to_time, str2bool
45
51
46 log = logging.getLogger(__name__)
52 log = logging.getLogger(__name__)
47
53
@@ -64,7 +70,49 b' class UsersController(BaseController):'
64 """GET /users: All items in the collection"""
70 """GET /users: All items in the collection"""
65 # url('users')
71 # url('users')
66
72
67 c.users_list = self.sa.query(User).all()
73 c.users_list = User.query().order_by(User.username).all()
74
75 users_data = []
76 total_records = len(c.users_list)
77 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
78 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
79
80 grav_tmpl = lambda user_email, size: (
81 template.get_def("user_gravatar")
82 .render(user_email, size, _=_, h=h, c=c))
83
84 user_lnk = lambda user_id, username: (
85 template.get_def("user_name")
86 .render(user_id, username, _=_, h=h, c=c))
87
88 user_actions = lambda user_id, username: (
89 template.get_def("user_actions")
90 .render(user_id, username, _=_, h=h, c=c))
91
92 for user in c.users_list:
93
94 users_data.append({
95 "gravatar": grav_tmpl(user. email, 24),
96 "raw_username": user.username,
97 "username": user_lnk(user.user_id, user.username),
98 "firstname": user.name,
99 "lastname": user.lastname,
100 "last_login": h.fmt_date(user.last_login),
101 "last_login_raw": datetime_to_time(user.last_login),
102 "active": h.bool2icon(user.active),
103 "admin": h.bool2icon(user.admin),
104 "ldap": h.bool2icon(bool(user.ldap_dn)),
105 "action": user_actions(user.user_id, user.username),
106 })
107
108 c.data = json.dumps({
109 "totalRecords": total_records,
110 "startIndex": 0,
111 "sort": None,
112 "dir": "asc",
113 "records": users_data
114 })
115
68 return render('admin/users/users.html')
116 return render('admin/users/users.html')
69
117
70 def create(self):
118 def create(self):
@@ -76,10 +124,12 b' class UsersController(BaseController):'
76 try:
124 try:
77 form_result = user_form.to_python(dict(request.POST))
125 form_result = user_form.to_python(dict(request.POST))
78 user_model.create(form_result)
126 user_model.create(form_result)
79 h.flash(_('created user %s') % form_result['username'],
127 usr = form_result['username']
128 action_logger(self.rhodecode_user, 'admin_created_user:%s' % usr,
129 None, self.ip_addr, self.sa)
130 h.flash(_('created user %s') % usr,
80 category='success')
131 category='success')
81 Session.commit()
132 Session().commit()
82 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
83 except formencode.Invalid, errors:
133 except formencode.Invalid, errors:
84 return htmlfill.render(
134 return htmlfill.render(
85 render('admin/users/user_add.html'),
135 render('admin/users/user_add.html'),
@@ -108,22 +158,31 b' class UsersController(BaseController):'
108 # url('user', id=ID)
158 # url('user', id=ID)
109 user_model = UserModel()
159 user_model = UserModel()
110 c.user = user_model.get(id)
160 c.user = user_model.get(id)
111
161 c.perm_user = AuthUser(user_id=id)
112 _form = UserForm(edit=True, old_data={'user_id': id,
162 _form = UserForm(edit=True, old_data={'user_id': id,
113 'email': c.user.email})()
163 'email': c.user.email})()
114 form_result = {}
164 form_result = {}
115 try:
165 try:
116 form_result = _form.to_python(dict(request.POST))
166 form_result = _form.to_python(dict(request.POST))
117 user_model.update(id, form_result)
167 user_model.update(id, form_result)
168 usr = form_result['username']
169 action_logger(self.rhodecode_user, 'admin_updated_user:%s' % usr,
170 None, self.ip_addr, self.sa)
118 h.flash(_('User updated successfully'), category='success')
171 h.flash(_('User updated successfully'), category='success')
119 Session.commit()
172 Session().commit()
120 except formencode.Invalid, errors:
173 except formencode.Invalid, errors:
174 c.user_email_map = UserEmailMap.query()\
175 .filter(UserEmailMap.user == c.user).all()
176 defaults = errors.value
121 e = errors.error_dict or {}
177 e = errors.error_dict or {}
122 perm = Permission.get_by_key('hg.create.repository')
178 defaults.update({
123 e.update({'create_repo_perm': user_model.has_perm(id, perm)})
179 'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'),
180 'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'),
181 '_method': 'put'
182 })
124 return htmlfill.render(
183 return htmlfill.render(
125 render('admin/users/user_edit.html'),
184 render('admin/users/user_edit.html'),
126 defaults=errors.value,
185 defaults=defaults,
127 errors=e,
186 errors=e,
128 prefix_error=False,
187 prefix_error=False,
129 encoding="UTF-8")
188 encoding="UTF-8")
@@ -131,8 +190,7 b' class UsersController(BaseController):'
131 log.error(traceback.format_exc())
190 log.error(traceback.format_exc())
132 h.flash(_('error occurred during update of user %s') \
191 h.flash(_('error occurred during update of user %s') \
133 % form_result.get('username'), category='error')
192 % form_result.get('username'), category='error')
134
193 return redirect(url('edit_user', id=id))
135 return redirect(url('users'))
136
194
137 def delete(self, id):
195 def delete(self, id):
138 """DELETE /users/id: Delete an existing item"""
196 """DELETE /users/id: Delete an existing item"""
@@ -142,10 +200,10 b' class UsersController(BaseController):'
142 # h.form(url('delete_user', id=ID),
200 # h.form(url('delete_user', id=ID),
143 # method='delete')
201 # method='delete')
144 # url('user', id=ID)
202 # url('user', id=ID)
145 user_model = UserModel()
203 usr = User.get_or_404(id)
146 try:
204 try:
147 user_model.delete(id)
205 UserModel().delete(usr)
148 Session.commit()
206 Session().commit()
149 h.flash(_('successfully deleted user'), category='success')
207 h.flash(_('successfully deleted user'), category='success')
150 except (UserOwnsReposException, DefaultUserException), e:
208 except (UserOwnsReposException, DefaultUserException), e:
151 h.flash(e, category='warning')
209 h.flash(e, category='warning')
@@ -162,19 +220,24 b' class UsersController(BaseController):'
162 def edit(self, id, format='html'):
220 def edit(self, id, format='html'):
163 """GET /users/id/edit: Form to edit an existing item"""
221 """GET /users/id/edit: Form to edit an existing item"""
164 # url('edit_user', id=ID)
222 # url('edit_user', id=ID)
165 c.user = User.get(id)
223 c.user = User.get_or_404(id)
166 if not c.user:
224
167 return redirect(url('users'))
168 if c.user.username == 'default':
225 if c.user.username == 'default':
169 h.flash(_("You can't edit this user"), category='warning')
226 h.flash(_("You can't edit this user"), category='warning')
170 return redirect(url('users'))
227 return redirect(url('users'))
228
229 c.perm_user = AuthUser(user_id=id)
171 c.user.permissions = {}
230 c.user.permissions = {}
172 c.granted_permissions = UserModel().fill_perms(c.user)\
231 c.granted_permissions = UserModel().fill_perms(c.user)\
173 .permissions['global']
232 .permissions['global']
174
233 c.user_email_map = UserEmailMap.query()\
234 .filter(UserEmailMap.user == c.user).all()
235 user_model = UserModel()
175 defaults = c.user.get_dict()
236 defaults = c.user.get_dict()
176 perm = Permission.get_by_key('hg.create.repository')
237 defaults.update({
177 defaults.update({'create_repo_perm': UserModel().has_perm(id, perm)})
238 'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'),
239 'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'),
240 })
178
241
179 return htmlfill.render(
242 return htmlfill.render(
180 render('admin/users/user_edit.html'),
243 render('admin/users/user_edit.html'),
@@ -186,26 +249,72 b' class UsersController(BaseController):'
186 def update_perm(self, id):
249 def update_perm(self, id):
187 """PUT /users_perm/id: Update an existing item"""
250 """PUT /users_perm/id: Update an existing item"""
188 # url('user_perm', id=ID, method='put')
251 # url('user_perm', id=ID, method='put')
252 usr = User.get_or_404(id)
253 grant_create_perm = str2bool(request.POST.get('create_repo_perm'))
254 grant_fork_perm = str2bool(request.POST.get('fork_repo_perm'))
255 inherit_perms = str2bool(request.POST.get('inherit_default_permissions'))
189
256
190 grant_perm = request.POST.get('create_repo_perm', False)
191 user_model = UserModel()
257 user_model = UserModel()
192
258
193 if grant_perm:
259 try:
194 perm = Permission.get_by_key('hg.create.none')
260 usr.inherit_default_permissions = inherit_perms
195 user_model.revoke_perm(id, perm)
261 Session().add(usr)
262
263 if grant_create_perm:
264 user_model.revoke_perm(usr, 'hg.create.none')
265 user_model.grant_perm(usr, 'hg.create.repository')
266 h.flash(_("Granted 'repository create' permission to user"),
267 category='success')
268 else:
269 user_model.revoke_perm(usr, 'hg.create.repository')
270 user_model.grant_perm(usr, 'hg.create.none')
271 h.flash(_("Revoked 'repository create' permission to user"),
272 category='success')
273
274 if grant_fork_perm:
275 user_model.revoke_perm(usr, 'hg.fork.none')
276 user_model.grant_perm(usr, 'hg.fork.repository')
277 h.flash(_("Granted 'repository fork' permission to user"),
278 category='success')
279 else:
280 user_model.revoke_perm(usr, 'hg.fork.repository')
281 user_model.grant_perm(usr, 'hg.fork.none')
282 h.flash(_("Revoked 'repository fork' permission to user"),
283 category='success')
196
284
197 perm = Permission.get_by_key('hg.create.repository')
285 Session().commit()
198 user_model.grant_perm(id, perm)
286 except Exception:
199 h.flash(_("Granted 'repository create' permission to user"),
287 log.error(traceback.format_exc())
200 category='success')
288 h.flash(_('An error occurred during permissions saving'),
201 Session.commit()
289 category='error')
202 else:
290 return redirect(url('edit_user', id=id))
203 perm = Permission.get_by_key('hg.create.repository')
291
204 user_model.revoke_perm(id, perm)
292 def add_email(self, id):
293 """POST /user_emails:Add an existing item"""
294 # url('user_emails', id=ID, method='put')
295
296 #TODO: validation and form !!!
297 email = request.POST.get('new_email')
298 user_model = UserModel()
205
299
206 perm = Permission.get_by_key('hg.create.none')
300 try:
207 user_model.grant_perm(id, perm)
301 user_model.add_extra_email(id, email)
208 h.flash(_("Revoked 'repository create' permission to user"),
302 Session().commit()
209 category='success')
303 h.flash(_("Added email %s to user") % email, category='success')
210 Session.commit()
304 except formencode.Invalid, error:
305 msg = error.error_dict['email']
306 h.flash(msg, category='error')
307 except Exception:
308 log.error(traceback.format_exc())
309 h.flash(_('An error occurred during email saving'),
310 category='error')
211 return redirect(url('edit_user', id=id))
311 return redirect(url('edit_user', id=id))
312
313 def delete_email(self, id):
314 """DELETE /user_emails_delete/id: Delete an existing item"""
315 # url('user_emails_delete', id=ID, method='delete')
316 user_model = UserModel()
317 user_model.delete_extra_email(id, request.POST.get('del_email'))
318 Session().commit()
319 h.flash(_("Removed email from user"), category='success')
320 return redirect(url('edit_user', id=id))
@@ -34,15 +34,16 b' from pylons.i18n.translation import _'
34
34
35 from rhodecode.lib import helpers as h
35 from rhodecode.lib import helpers as h
36 from rhodecode.lib.exceptions import UsersGroupsAssignedException
36 from rhodecode.lib.exceptions import UsersGroupsAssignedException
37 from rhodecode.lib.utils2 import safe_unicode
37 from rhodecode.lib.utils2 import safe_unicode, str2bool
38 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
38 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
39 from rhodecode.lib.base import BaseController, render
39 from rhodecode.lib.base import BaseController, render
40
40
41 from rhodecode.model.users_group import UsersGroupModel
41 from rhodecode.model.users_group import UsersGroupModel
42
42
43 from rhodecode.model.db import User, UsersGroup, Permission, UsersGroupToPerm
43 from rhodecode.model.db import User, UsersGroup
44 from rhodecode.model.forms import UsersGroupForm
44 from rhodecode.model.forms import UsersGroupForm
45 from rhodecode.model.meta import Session
45 from rhodecode.model.meta import Session
46 from rhodecode.lib.utils import action_logger
46
47
47 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
48
49
@@ -64,7 +65,7 b' class UsersGroupsController(BaseControll'
64 def index(self, format='html'):
65 def index(self, format='html'):
65 """GET /users_groups: All items in the collection"""
66 """GET /users_groups: All items in the collection"""
66 # url('users_groups')
67 # url('users_groups')
67 c.users_groups_list = self.sa.query(UsersGroup).all()
68 c.users_groups_list = UsersGroup().query().all()
68 return render('admin/users_groups/users_groups.html')
69 return render('admin/users_groups/users_groups.html')
69
70
70 def create(self):
71 def create(self):
@@ -76,10 +77,12 b' class UsersGroupsController(BaseControll'
76 form_result = users_group_form.to_python(dict(request.POST))
77 form_result = users_group_form.to_python(dict(request.POST))
77 UsersGroupModel().create(name=form_result['users_group_name'],
78 UsersGroupModel().create(name=form_result['users_group_name'],
78 active=form_result['users_group_active'])
79 active=form_result['users_group_active'])
79 h.flash(_('created users group %s') \
80 gr = form_result['users_group_name']
80 % form_result['users_group_name'], category='success')
81 action_logger(self.rhodecode_user,
81 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
82 'admin_created_users_group:%s' % gr,
82 Session.commit()
83 None, self.ip_addr, self.sa)
84 h.flash(_('created users group %s') % gr, category='success')
85 Session().commit()
83 except formencode.Invalid, errors:
86 except formencode.Invalid, errors:
84 return htmlfill.render(
87 return htmlfill.render(
85 render('admin/users_groups/users_group_add.html'),
88 render('admin/users_groups/users_group_add.html'),
@@ -114,7 +117,7 b' class UsersGroupsController(BaseControll'
114 c.group_members_obj]
117 c.group_members_obj]
115
118
116 c.available_members = [(x.user_id, x.username) for x in
119 c.available_members = [(x.user_id, x.username) for x in
117 self.sa.query(User).all()]
120 User.query().all()]
118
121
119 available_members = [safe_unicode(x[0]) for x in c.available_members]
122 available_members = [safe_unicode(x[0]) for x in c.available_members]
120
123
@@ -125,21 +128,27 b' class UsersGroupsController(BaseControll'
125 try:
128 try:
126 form_result = users_group_form.to_python(request.POST)
129 form_result = users_group_form.to_python(request.POST)
127 UsersGroupModel().update(c.users_group, form_result)
130 UsersGroupModel().update(c.users_group, form_result)
128 h.flash(_('updated users group %s') \
131 gr = form_result['users_group_name']
129 % form_result['users_group_name'],
132 action_logger(self.rhodecode_user,
130 category='success')
133 'admin_updated_users_group:%s' % gr,
131 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
134 None, self.ip_addr, self.sa)
132 Session.commit()
135 h.flash(_('updated users group %s') % gr, category='success')
136 Session().commit()
133 except formencode.Invalid, errors:
137 except formencode.Invalid, errors:
138 ug_model = UsersGroupModel()
139 defaults = errors.value
134 e = errors.error_dict or {}
140 e = errors.error_dict or {}
135
141 defaults.update({
136 perm = Permission.get_by_key('hg.create.repository')
142 'create_repo_perm': ug_model.has_perm(id,
137 e.update({'create_repo_perm':
143 'hg.create.repository'),
138 UsersGroupModel().has_perm(id, perm)})
144 'fork_repo_perm': ug_model.has_perm(id,
145 'hg.fork.repository'),
146 '_method': 'put'
147 })
139
148
140 return htmlfill.render(
149 return htmlfill.render(
141 render('admin/users_groups/users_group_edit.html'),
150 render('admin/users_groups/users_group_edit.html'),
142 defaults=errors.value,
151 defaults=defaults,
143 errors=e,
152 errors=e,
144 prefix_error=False,
153 prefix_error=False,
145 encoding="UTF-8")
154 encoding="UTF-8")
@@ -148,7 +157,7 b' class UsersGroupsController(BaseControll'
148 h.flash(_('error occurred during update of users group %s') \
157 h.flash(_('error occurred during update of users group %s') \
149 % request.POST.get('users_group_name'), category='error')
158 % request.POST.get('users_group_name'), category='error')
150
159
151 return redirect(url('users_groups'))
160 return redirect(url('edit_users_group', id=id))
152
161
153 def delete(self, id):
162 def delete(self, id):
154 """DELETE /users_groups/id: Delete an existing item"""
163 """DELETE /users_groups/id: Delete an existing item"""
@@ -158,10 +167,10 b' class UsersGroupsController(BaseControll'
158 # h.form(url('users_group', id=ID),
167 # h.form(url('users_group', id=ID),
159 # method='delete')
168 # method='delete')
160 # url('users_group', id=ID)
169 # url('users_group', id=ID)
161
170 usr_gr = UsersGroup.get_or_404(id)
162 try:
171 try:
163 UsersGroupModel().delete(id)
172 UsersGroupModel().delete(usr_gr)
164 Session.commit()
173 Session().commit()
165 h.flash(_('successfully deleted users group'), category='success')
174 h.flash(_('successfully deleted users group'), category='success')
166 except UsersGroupsAssignedException, e:
175 except UsersGroupsAssignedException, e:
167 h.flash(e, category='error')
176 h.flash(e, category='error')
@@ -179,20 +188,23 b' class UsersGroupsController(BaseControll'
179 """GET /users_groups/id/edit: Form to edit an existing item"""
188 """GET /users_groups/id/edit: Form to edit an existing item"""
180 # url('edit_users_group', id=ID)
189 # url('edit_users_group', id=ID)
181
190
182 c.users_group = self.sa.query(UsersGroup).get(id)
191 c.users_group = UsersGroup.get_or_404(id)
183 if not c.users_group:
184 return redirect(url('users_groups'))
185
192
186 c.users_group.permissions = {}
193 c.users_group.permissions = {}
187 c.group_members_obj = [x.user for x in c.users_group.members]
194 c.group_members_obj = [x.user for x in c.users_group.members]
188 c.group_members = [(x.user_id, x.username) for x in
195 c.group_members = [(x.user_id, x.username) for x in
189 c.group_members_obj]
196 c.group_members_obj]
190 c.available_members = [(x.user_id, x.username) for x in
197 c.available_members = [(x.user_id, x.username) for x in
191 self.sa.query(User).all()]
198 User.query().all()]
199 ug_model = UsersGroupModel()
192 defaults = c.users_group.get_dict()
200 defaults = c.users_group.get_dict()
193 perm = Permission.get_by_key('hg.create.repository')
201 defaults.update({
194 defaults.update({'create_repo_perm':
202 'create_repo_perm': ug_model.has_perm(c.users_group,
195 UsersGroupModel().has_perm(c.users_group, perm)})
203 'hg.create.repository'),
204 'fork_repo_perm': ug_model.has_perm(c.users_group,
205 'hg.fork.repository'),
206 })
207
196 return htmlfill.render(
208 return htmlfill.render(
197 render('admin/users_groups/users_group_edit.html'),
209 render('admin/users_groups/users_group_edit.html'),
198 defaults=defaults,
210 defaults=defaults,
@@ -204,25 +216,43 b' class UsersGroupsController(BaseControll'
204 """PUT /users_perm/id: Update an existing item"""
216 """PUT /users_perm/id: Update an existing item"""
205 # url('users_group_perm', id=ID, method='put')
217 # url('users_group_perm', id=ID, method='put')
206
218
207 grant_perm = request.POST.get('create_repo_perm', False)
219 users_group = UsersGroup.get_or_404(id)
220 grant_create_perm = str2bool(request.POST.get('create_repo_perm'))
221 grant_fork_perm = str2bool(request.POST.get('fork_repo_perm'))
222 inherit_perms = str2bool(request.POST.get('inherit_default_permissions'))
208
223
209 if grant_perm:
224 usersgroup_model = UsersGroupModel()
210 perm = Permission.get_by_key('hg.create.none')
211 UsersGroupModel().revoke_perm(id, perm)
212
225
213 perm = Permission.get_by_key('hg.create.repository')
226 try:
214 UsersGroupModel().grant_perm(id, perm)
227 users_group.inherit_default_permissions = inherit_perms
215 h.flash(_("Granted 'repository create' permission to user"),
228 Session().add(users_group)
216 category='success')
217
229
218 Session.commit()
230 if grant_create_perm:
219 else:
231 usersgroup_model.revoke_perm(id, 'hg.create.none')
220 perm = Permission.get_by_key('hg.create.repository')
232 usersgroup_model.grant_perm(id, 'hg.create.repository')
221 UsersGroupModel().revoke_perm(id, perm)
233 h.flash(_("Granted 'repository create' permission to users group"),
234 category='success')
235 else:
236 usersgroup_model.revoke_perm(id, 'hg.create.repository')
237 usersgroup_model.grant_perm(id, 'hg.create.none')
238 h.flash(_("Revoked 'repository create' permission to users group"),
239 category='success')
222
240
223 perm = Permission.get_by_key('hg.create.none')
241 if grant_fork_perm:
224 UsersGroupModel().grant_perm(id, perm)
242 usersgroup_model.revoke_perm(id, 'hg.fork.none')
225 h.flash(_("Revoked 'repository create' permission to user"),
243 usersgroup_model.grant_perm(id, 'hg.fork.repository')
226 category='success')
244 h.flash(_("Granted 'repository fork' permission to users group"),
227 Session.commit()
245 category='success')
246 else:
247 usersgroup_model.revoke_perm(id, 'hg.fork.repository')
248 usersgroup_model.grant_perm(id, 'hg.fork.none')
249 h.flash(_("Revoked 'repository fork' permission to users group"),
250 category='success')
251
252 Session().commit()
253 except Exception:
254 log.error(traceback.format_exc())
255 h.flash(_('An error occurred during permissions saving'),
256 category='error')
257
228 return redirect(url('edit_users_group', id=id))
258 return redirect(url('edit_users_group', id=id))
@@ -30,6 +30,7 b' import logging'
30 import types
30 import types
31 import urllib
31 import urllib
32 import traceback
32 import traceback
33 import time
33
34
34 from rhodecode.lib.compat import izip_longest, json
35 from rhodecode.lib.compat import izip_longest, json
35
36
@@ -43,6 +44,8 b' HTTPBadRequest, HTTPError'
43
44
44 from rhodecode.model.db import User
45 from rhodecode.model.db import User
45 from rhodecode.lib.auth import AuthUser
46 from rhodecode.lib.auth import AuthUser
47 from rhodecode.lib.base import _get_ip_addr, _get_access_path
48 from rhodecode.lib.utils2 import safe_unicode
46
49
47 log = logging.getLogger('JSONRPC')
50 log = logging.getLogger('JSONRPC')
48
51
@@ -57,15 +60,16 b' class JSONRPCError(BaseException):'
57 return str(self.message)
60 return str(self.message)
58
61
59
62
60 def jsonrpc_error(message, code=None):
63 def jsonrpc_error(message, retid=None, code=None):
61 """
64 """
62 Generate a Response object with a JSON-RPC error body
65 Generate a Response object with a JSON-RPC error body
63 """
66 """
64 from pylons.controllers.util import Response
67 from pylons.controllers.util import Response
65 resp = Response(body=json.dumps(dict(id=None, result=None, error=message)),
68 return Response(
66 status=code,
69 body=json.dumps(dict(id=retid, result=None, error=message)),
67 content_type='application/json')
70 status=code,
68 return resp
71 content_type='application/json'
72 )
69
73
70
74
71 class JSONRPCController(WSGIController):
75 class JSONRPCController(WSGIController):
@@ -94,9 +98,12 b' class JSONRPCController(WSGIController):'
94 Parse the request body as JSON, look up the method on the
98 Parse the request body as JSON, look up the method on the
95 controller and if it exists, dispatch to it.
99 controller and if it exists, dispatch to it.
96 """
100 """
101 start = time.time()
102 self._req_id = None
97 if 'CONTENT_LENGTH' not in environ:
103 if 'CONTENT_LENGTH' not in environ:
98 log.debug("No Content-Length")
104 log.debug("No Content-Length")
99 return jsonrpc_error(message="No Content-Length in request")
105 return jsonrpc_error(retid=self._req_id,
106 message="No Content-Length in request")
100 else:
107 else:
101 length = environ['CONTENT_LENGTH'] or 0
108 length = environ['CONTENT_LENGTH'] or 0
102 length = int(environ['CONTENT_LENGTH'])
109 length = int(environ['CONTENT_LENGTH'])
@@ -104,7 +111,8 b' class JSONRPCController(WSGIController):'
104
111
105 if length == 0:
112 if length == 0:
106 log.debug("Content-Length is 0")
113 log.debug("Content-Length is 0")
107 return jsonrpc_error(message="Content-Length is 0")
114 return jsonrpc_error(retid=self._req_id,
115 message="Content-Length is 0")
108
116
109 raw_body = environ['wsgi.input'].read(length)
117 raw_body = environ['wsgi.input'].read(length)
110
118
@@ -112,7 +120,8 b' class JSONRPCController(WSGIController):'
112 json_body = json.loads(urllib.unquote_plus(raw_body))
120 json_body = json.loads(urllib.unquote_plus(raw_body))
113 except ValueError, e:
121 except ValueError, e:
114 # catch JSON errors Here
122 # catch JSON errors Here
115 return jsonrpc_error(message="JSON parse error ERR:%s RAW:%r" \
123 return jsonrpc_error(retid=self._req_id,
124 message="JSON parse error ERR:%s RAW:%r" \
116 % (e, urllib.unquote_plus(raw_body)))
125 % (e, urllib.unquote_plus(raw_body)))
117
126
118 # check AUTH based on API KEY
127 # check AUTH based on API KEY
@@ -126,22 +135,26 b' class JSONRPCController(WSGIController):'
126 self._request_params)
135 self._request_params)
127 )
136 )
128 except KeyError, e:
137 except KeyError, e:
129 return jsonrpc_error(message='Incorrect JSON query missing %s' % e)
138 return jsonrpc_error(retid=self._req_id,
139 message='Incorrect JSON query missing %s' % e)
130
140
131 # check if we can find this session using api_key
141 # check if we can find this session using api_key
132 try:
142 try:
133 u = User.get_by_api_key(self._req_api_key)
143 u = User.get_by_api_key(self._req_api_key)
134 if u is None:
144 if u is None:
135 return jsonrpc_error(message='Invalid API KEY')
145 return jsonrpc_error(retid=self._req_id,
146 message='Invalid API KEY')
136 auth_u = AuthUser(u.user_id, self._req_api_key)
147 auth_u = AuthUser(u.user_id, self._req_api_key)
137 except Exception, e:
148 except Exception, e:
138 return jsonrpc_error(message='Invalid API KEY')
149 return jsonrpc_error(retid=self._req_id,
150 message='Invalid API KEY')
139
151
140 self._error = None
152 self._error = None
141 try:
153 try:
142 self._func = self._find_method()
154 self._func = self._find_method()
143 except AttributeError, e:
155 except AttributeError, e:
144 return jsonrpc_error(message=str(e))
156 return jsonrpc_error(retid=self._req_id,
157 message=str(e))
145
158
146 # now that we have a method, add self._req_params to
159 # now that we have a method, add self._req_params to
147 # self.kargs and dispatch control to WGIController
160 # self.kargs and dispatch control to WGIController
@@ -164,9 +177,12 b' class JSONRPCController(WSGIController):'
164 USER_SESSION_ATTR = 'apiuser'
177 USER_SESSION_ATTR = 'apiuser'
165
178
166 if USER_SESSION_ATTR not in arglist:
179 if USER_SESSION_ATTR not in arglist:
167 return jsonrpc_error(message='This method [%s] does not support '
180 return jsonrpc_error(
168 'authentication (missing %s param)' %
181 retid=self._req_id,
169 (self._func.__name__, USER_SESSION_ATTR))
182 message='This method [%s] does not support '
183 'authentication (missing %s param)' % (
184 self._func.__name__, USER_SESSION_ATTR)
185 )
170
186
171 # get our arglist and check if we provided them as args
187 # get our arglist and check if we provided them as args
172 for arg, default in func_kwargs.iteritems():
188 for arg, default in func_kwargs.iteritems():
@@ -179,6 +195,7 b' class JSONRPCController(WSGIController):'
179 # NotImplementedType (default_empty)
195 # NotImplementedType (default_empty)
180 if (default == default_empty and arg not in self._request_params):
196 if (default == default_empty and arg not in self._request_params):
181 return jsonrpc_error(
197 return jsonrpc_error(
198 retid=self._req_id,
182 message=(
199 message=(
183 'Missing non optional `%s` arg in JSON DATA' % arg
200 'Missing non optional `%s` arg in JSON DATA' % arg
184 )
201 )
@@ -205,7 +222,10 b' class JSONRPCController(WSGIController):'
205 headers.append(('Content-Length', str(len(output[0]))))
222 headers.append(('Content-Length', str(len(output[0]))))
206 replace_header(headers, 'Content-Type', 'application/json')
223 replace_header(headers, 'Content-Type', 'application/json')
207 start_response(status[0], headers, exc_info[0])
224 start_response(status[0], headers, exc_info[0])
208
225 log.info('IP: %s Request to %s time: %.3fs' % (
226 _get_ip_addr(environ),
227 safe_unicode(_get_access_path(environ)), time.time() - start)
228 )
209 return output
229 return output
210
230
211 def _dispatch_call(self):
231 def _dispatch_call(self):
This diff has been collapsed as it changes many lines, (785 lines changed) Show them Hide them
@@ -31,18 +31,100 b' import logging'
31 from rhodecode.controllers.api import JSONRPCController, JSONRPCError
31 from rhodecode.controllers.api import JSONRPCController, JSONRPCError
32 from rhodecode.lib.auth import HasPermissionAllDecorator, \
32 from rhodecode.lib.auth import HasPermissionAllDecorator, \
33 HasPermissionAnyDecorator, PasswordGenerator, AuthUser
33 HasPermissionAnyDecorator, PasswordGenerator, AuthUser
34
34 from rhodecode.lib.utils import map_groups, repo2db_mapper
35 from rhodecode.model.meta import Session
35 from rhodecode.model.meta import Session
36 from rhodecode.model.scm import ScmModel
36 from rhodecode.model.scm import ScmModel
37 from rhodecode.model.db import User, UsersGroup, Repository
38 from rhodecode.model.repo import RepoModel
37 from rhodecode.model.repo import RepoModel
39 from rhodecode.model.user import UserModel
38 from rhodecode.model.user import UserModel
40 from rhodecode.model.users_group import UsersGroupModel
39 from rhodecode.model.users_group import UsersGroupModel
41 from rhodecode.lib.utils import map_groups
40 from rhodecode.model.permission import PermissionModel
41 from rhodecode.model.db import Repository
42
42
43 log = logging.getLogger(__name__)
43 log = logging.getLogger(__name__)
44
44
45
45
46 class Optional(object):
47 """
48 Defines an optional parameter::
49
50 param = param.getval() if isinstance(param, Optional) else param
51 param = param() if isinstance(param, Optional) else param
52
53 is equivalent of::
54
55 param = Optional.extract(param)
56
57 """
58 def __init__(self, type_):
59 self.type_ = type_
60
61 def __repr__(self):
62 return '<Optional:%s>' % self.type_.__repr__()
63
64 def __call__(self):
65 return self.getval()
66
67 def getval(self):
68 """
69 returns value from this Optional instance
70 """
71 return self.type_
72
73 @classmethod
74 def extract(cls, val):
75 if isinstance(val, cls):
76 return val.getval()
77 return val
78
79
80 def get_user_or_error(userid):
81 """
82 Get user by id or name or return JsonRPCError if not found
83
84 :param userid:
85 """
86 user = UserModel().get_user(userid)
87 if user is None:
88 raise JSONRPCError("user `%s` does not exist" % userid)
89 return user
90
91
92 def get_repo_or_error(repoid):
93 """
94 Get repo by id or name or return JsonRPCError if not found
95
96 :param userid:
97 """
98 repo = RepoModel().get_repo(repoid)
99 if repo is None:
100 raise JSONRPCError('repository `%s` does not exist' % (repoid))
101 return repo
102
103
104 def get_users_group_or_error(usersgroupid):
105 """
106 Get users group by id or name or return JsonRPCError if not found
107
108 :param userid:
109 """
110 users_group = UsersGroupModel().get_group(usersgroupid)
111 if users_group is None:
112 raise JSONRPCError('users group `%s` does not exist' % usersgroupid)
113 return users_group
114
115
116 def get_perm_or_error(permid):
117 """
118 Get permission by id or name or return JsonRPCError if not found
119
120 :param userid:
121 """
122 perm = PermissionModel().get_permission_by_name(permid)
123 if perm is None:
124 raise JSONRPCError('permission `%s` does not exist' % (permid))
125 return perm
126
127
46 class ApiController(JSONRPCController):
128 class ApiController(JSONRPCController):
47 """
129 """
48 API Controller
130 API Controller
@@ -60,23 +142,74 b' class ApiController(JSONRPCController):'
60 """
142 """
61
143
62 @HasPermissionAllDecorator('hg.admin')
144 @HasPermissionAllDecorator('hg.admin')
63 def pull(self, apiuser, repo_name):
145 def pull(self, apiuser, repoid):
64 """
146 """
65 Dispatch pull action on given repo
147 Dispatch pull action on given repo
66
148
149 :param apiuser:
150 :param repoid:
151 """
67
152
68 :param user:
153 repo = get_repo_or_error(repoid)
69 :param repo_name:
154
155 try:
156 ScmModel().pull_changes(repo.repo_name,
157 self.rhodecode_user.username)
158 return 'Pulled from `%s`' % repo.repo_name
159 except Exception:
160 log.error(traceback.format_exc())
161 raise JSONRPCError(
162 'Unable to pull changes from `%s`' % repo.repo_name
163 )
164
165 @HasPermissionAllDecorator('hg.admin')
166 def rescan_repos(self, apiuser, remove_obsolete=Optional(False)):
167 """
168 Dispatch rescan repositories action. If remove_obsolete is set
169 than also delete repos that are in database but not in the filesystem.
170 aka "clean zombies"
171
172 :param apiuser:
173 :param remove_obsolete:
70 """
174 """
71
175
72 if Repository.is_valid(repo_name) is False:
73 raise JSONRPCError('Unknown repo "%s"' % repo_name)
74
75 try:
176 try:
76 ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
177 rm_obsolete = Optional.extract(remove_obsolete)
77 return 'Pulled from %s' % repo_name
178 added, removed = repo2db_mapper(ScmModel().repo_scan(),
179 remove_obsolete=rm_obsolete)
180 return {'added': added, 'removed': removed}
78 except Exception:
181 except Exception:
79 raise JSONRPCError('Unable to pull changes from "%s"' % repo_name)
182 log.error(traceback.format_exc())
183 raise JSONRPCError(
184 'Error occurred during rescan repositories action'
185 )
186
187 @HasPermissionAllDecorator('hg.admin')
188 def lock(self, apiuser, repoid, userid, locked):
189 """
190 Set locking state on particular repository by given user
191
192 :param apiuser:
193 :param repoid:
194 :param userid:
195 :param locked:
196 """
197 repo = get_repo_or_error(repoid)
198 user = get_user_or_error(userid)
199 locked = bool(locked)
200 try:
201 if locked:
202 Repository.lock(repo, user.user_id)
203 else:
204 Repository.unlock(repo)
205
206 return ('User `%s` set lock state for repo `%s` to `%s`'
207 % (user.username, repo.repo_name, locked))
208 except Exception:
209 log.error(traceback.format_exc())
210 raise JSONRPCError(
211 'Error occurred locking repository `%s`' % repo.repo_name
212 )
80
213
81 @HasPermissionAllDecorator('hg.admin')
214 @HasPermissionAllDecorator('hg.admin')
82 def get_user(self, apiuser, userid):
215 def get_user(self, apiuser, userid):
@@ -84,25 +217,13 b' class ApiController(JSONRPCController):'
84 Get a user by username
217 Get a user by username
85
218
86 :param apiuser:
219 :param apiuser:
87 :param username:
220 :param userid:
88 """
221 """
89
222
90 user = UserModel().get_user(userid)
223 user = get_user_or_error(userid)
91 if user is None:
224 data = user.get_api_data()
92 return user
225 data['permissions'] = AuthUser(user_id=user.user_id).permissions
93
226 return data
94 return dict(
95 id=user.user_id,
96 username=user.username,
97 firstname=user.name,
98 lastname=user.lastname,
99 email=user.email,
100 active=user.active,
101 admin=user.admin,
102 ldap_dn=user.ldap_dn,
103 last_login=user.last_login,
104 permissions=AuthUser(user_id=user.user_id).permissions
105 )
106
227
107 @HasPermissionAllDecorator('hg.admin')
228 @HasPermissionAllDecorator('hg.admin')
108 def get_users(self, apiuser):
229 def get_users(self, apiuser):
@@ -113,124 +234,150 b' class ApiController(JSONRPCController):'
113 """
234 """
114
235
115 result = []
236 result = []
116 for user in User.getAll():
237 for user in UserModel().get_all():
117 result.append(
238 result.append(user.get_api_data())
118 dict(
119 id=user.user_id,
120 username=user.username,
121 firstname=user.name,
122 lastname=user.lastname,
123 email=user.email,
124 active=user.active,
125 admin=user.admin,
126 ldap_dn=user.ldap_dn,
127 last_login=user.last_login,
128 )
129 )
130 return result
239 return result
131
240
132 @HasPermissionAllDecorator('hg.admin')
241 @HasPermissionAllDecorator('hg.admin')
133 def create_user(self, apiuser, username, email, password, firstname=None,
242 def create_user(self, apiuser, username, email, password,
134 lastname=None, active=True, admin=False, ldap_dn=None):
243 firstname=Optional(None), lastname=Optional(None),
244 active=Optional(True), admin=Optional(False),
245 ldap_dn=Optional(None)):
135 """
246 """
136 Create new user
247 Create new user
137
248
138 :param apiuser:
249 :param apiuser:
139 :param username:
250 :param username:
251 :param email:
140 :param password:
252 :param password:
141 :param email:
253 :param firstname:
142 :param name:
143 :param lastname:
254 :param lastname:
144 :param active:
255 :param active:
145 :param admin:
256 :param admin:
146 :param ldap_dn:
257 :param ldap_dn:
147 """
258 """
148 if User.get_by_username(username):
259
149 raise JSONRPCError("user %s already exist" % username)
260 if UserModel().get_by_username(username):
261 raise JSONRPCError("user `%s` already exist" % username)
150
262
151 if User.get_by_email(email, case_insensitive=True):
263 if UserModel().get_by_email(email, case_insensitive=True):
152 raise JSONRPCError("email %s already exist" % email)
264 raise JSONRPCError("email `%s` already exist" % email)
153
265
154 if ldap_dn:
266 if Optional.extract(ldap_dn):
155 # generate temporary password if ldap_dn
267 # generate temporary password if ldap_dn
156 password = PasswordGenerator().gen_password(length=8)
268 password = PasswordGenerator().gen_password(length=8)
157
269
158 try:
270 try:
159 usr = UserModel().create_or_update(
271 user = UserModel().create_or_update(
160 username, password, email, firstname,
272 username=Optional.extract(username),
161 lastname, active, admin, ldap_dn
273 password=Optional.extract(password),
274 email=Optional.extract(email),
275 firstname=Optional.extract(firstname),
276 lastname=Optional.extract(lastname),
277 active=Optional.extract(active),
278 admin=Optional.extract(admin),
279 ldap_dn=Optional.extract(ldap_dn)
162 )
280 )
163 Session.commit()
281 Session().commit()
164 return dict(
282 return dict(
165 id=usr.user_id,
283 msg='created new user `%s`' % username,
166 msg='created new user %s' % username
284 user=user.get_api_data()
167 )
285 )
168 except Exception:
286 except Exception:
169 log.error(traceback.format_exc())
287 log.error(traceback.format_exc())
170 raise JSONRPCError('failed to create user %s' % username)
288 raise JSONRPCError('failed to create user `%s`' % username)
171
289
172 @HasPermissionAllDecorator('hg.admin')
290 @HasPermissionAllDecorator('hg.admin')
173 def update_user(self, apiuser, userid, username, password, email,
291 def update_user(self, apiuser, userid, username=Optional(None),
174 firstname, lastname, active, admin, ldap_dn):
292 email=Optional(None), firstname=Optional(None),
293 lastname=Optional(None), active=Optional(None),
294 admin=Optional(None), ldap_dn=Optional(None),
295 password=Optional(None)):
175 """
296 """
176 Updates given user
297 Updates given user
177
298
178 :param apiuser:
299 :param apiuser:
300 :param userid:
179 :param username:
301 :param username:
180 :param password:
181 :param email:
302 :param email:
182 :param name:
303 :param firstname:
183 :param lastname:
304 :param lastname:
184 :param active:
305 :param active:
185 :param admin:
306 :param admin:
186 :param ldap_dn:
307 :param ldap_dn:
308 :param password:
187 """
309 """
188 if not UserModel().get_user(userid):
310
189 raise JSONRPCError("user %s does not exist" % username)
311 user = get_user_or_error(userid)
312
313 # call function and store only updated arguments
314 updates = {}
315
316 def store_update(attr, name):
317 if not isinstance(attr, Optional):
318 updates[name] = attr
190
319
191 try:
320 try:
192 usr = UserModel().create_or_update(
321
193 username, password, email, firstname,
322 store_update(username, 'username')
194 lastname, active, admin, ldap_dn
323 store_update(password, 'password')
195 )
324 store_update(email, 'email')
196 Session.commit()
325 store_update(firstname, 'name')
326 store_update(lastname, 'lastname')
327 store_update(active, 'active')
328 store_update(admin, 'admin')
329 store_update(ldap_dn, 'ldap_dn')
330
331 user = UserModel().update_user(user, **updates)
332 Session().commit()
197 return dict(
333 return dict(
198 id=usr.user_id,
334 msg='updated user ID:%s %s' % (user.user_id, user.username),
199 msg='updated user %s' % username
335 user=user.get_api_data()
200 )
336 )
201 except Exception:
337 except Exception:
202 log.error(traceback.format_exc())
338 log.error(traceback.format_exc())
203 raise JSONRPCError('failed to update user %s' % username)
339 raise JSONRPCError('failed to update user `%s`' % userid)
204
340
205 @HasPermissionAllDecorator('hg.admin')
341 @HasPermissionAllDecorator('hg.admin')
206 def get_users_group(self, apiuser, group_name):
342 def delete_user(self, apiuser, userid):
207 """"
343 """"
208 Get users group by name
344 Deletes an user
209
345
210 :param apiuser:
346 :param apiuser:
211 :param group_name:
347 :param userid:
212 """
348 """
349 user = get_user_or_error(userid)
213
350
214 users_group = UsersGroup.get_by_group_name(group_name)
351 try:
215 if not users_group:
352 UserModel().delete(userid)
216 return None
353 Session().commit()
354 return dict(
355 msg='deleted user ID:%s %s' % (user.user_id, user.username),
356 user=None
357 )
358 except Exception:
359 log.error(traceback.format_exc())
360 raise JSONRPCError('failed to delete ID:%s %s' % (user.user_id,
361 user.username))
362
363 @HasPermissionAllDecorator('hg.admin')
364 def get_users_group(self, apiuser, usersgroupid):
365 """"
366 Get users group by name or id
367
368 :param apiuser:
369 :param usersgroupid:
370 """
371 users_group = get_users_group_or_error(usersgroupid)
372
373 data = users_group.get_api_data()
217
374
218 members = []
375 members = []
219 for user in users_group.members:
376 for user in users_group.members:
220 user = user.user
377 user = user.user
221 members.append(dict(id=user.user_id,
378 members.append(user.get_api_data())
222 username=user.username,
379 data['members'] = members
223 firstname=user.name,
380 return data
224 lastname=user.lastname,
225 email=user.email,
226 active=user.active,
227 admin=user.admin,
228 ldap=user.ldap_dn))
229
230 return dict(id=users_group.users_group_id,
231 group_name=users_group.users_group_name,
232 active=users_group.users_group_active,
233 members=members)
234
381
235 @HasPermissionAllDecorator('hg.admin')
382 @HasPermissionAllDecorator('hg.admin')
236 def get_users_groups(self, apiuser):
383 def get_users_groups(self, apiuser):
@@ -241,107 +388,96 b' class ApiController(JSONRPCController):'
241 """
388 """
242
389
243 result = []
390 result = []
244 for users_group in UsersGroup.getAll():
391 for users_group in UsersGroupModel().get_all():
245 members = []
392 result.append(users_group.get_api_data())
246 for user in users_group.members:
247 user = user.user
248 members.append(dict(id=user.user_id,
249 username=user.username,
250 firstname=user.name,
251 lastname=user.lastname,
252 email=user.email,
253 active=user.active,
254 admin=user.admin,
255 ldap=user.ldap_dn))
256
257 result.append(dict(id=users_group.users_group_id,
258 group_name=users_group.users_group_name,
259 active=users_group.users_group_active,
260 members=members))
261 return result
393 return result
262
394
263 @HasPermissionAllDecorator('hg.admin')
395 @HasPermissionAllDecorator('hg.admin')
264 def create_users_group(self, apiuser, group_name, active=True):
396 def create_users_group(self, apiuser, group_name, active=Optional(True)):
265 """
397 """
266 Creates an new usergroup
398 Creates an new usergroup
267
399
400 :param apiuser:
268 :param group_name:
401 :param group_name:
269 :param active:
402 :param active:
270 """
403 """
271
404
272 if self.get_users_group(apiuser, group_name):
405 if UsersGroupModel().get_by_name(group_name):
273 raise JSONRPCError("users group %s already exist" % group_name)
406 raise JSONRPCError("users group `%s` already exist" % group_name)
274
407
275 try:
408 try:
409 active = Optional.extract(active)
276 ug = UsersGroupModel().create(name=group_name, active=active)
410 ug = UsersGroupModel().create(name=group_name, active=active)
277 Session.commit()
411 Session().commit()
278 return dict(id=ug.users_group_id,
412 return dict(
279 msg='created new users group %s' % group_name)
413 msg='created new users group `%s`' % group_name,
414 users_group=ug.get_api_data()
415 )
280 except Exception:
416 except Exception:
281 log.error(traceback.format_exc())
417 log.error(traceback.format_exc())
282 raise JSONRPCError('failed to create group %s' % group_name)
418 raise JSONRPCError('failed to create group `%s`' % group_name)
283
419
284 @HasPermissionAllDecorator('hg.admin')
420 @HasPermissionAllDecorator('hg.admin')
285 def add_user_to_users_group(self, apiuser, group_name, username):
421 def add_user_to_users_group(self, apiuser, usersgroupid, userid):
286 """"
422 """"
287 Add a user to a users group
423 Add a user to a users group
288
424
289 :param apiuser:
425 :param apiuser:
290 :param group_name:
426 :param usersgroupid:
291 :param username:
427 :param userid:
292 """
428 """
429 user = get_user_or_error(userid)
430 users_group = get_users_group_or_error(usersgroupid)
293
431
294 try:
432 try:
295 users_group = UsersGroup.get_by_group_name(group_name)
296 if not users_group:
297 raise JSONRPCError('unknown users group %s' % group_name)
298
299 user = User.get_by_username(username)
300 if user is None:
301 raise JSONRPCError('unknown user %s' % username)
302
303 ugm = UsersGroupModel().add_user_to_group(users_group, user)
433 ugm = UsersGroupModel().add_user_to_group(users_group, user)
304 success = True if ugm != True else False
434 success = True if ugm != True else False
305 msg = 'added member %s to users group %s' % (username, group_name)
435 msg = 'added member `%s` to users group `%s`' % (
436 user.username, users_group.users_group_name
437 )
306 msg = msg if success else 'User is already in that group'
438 msg = msg if success else 'User is already in that group'
307 Session.commit()
439 Session().commit()
308
440
309 return dict(
441 return dict(
310 id=ugm.users_group_member_id if ugm != True else None,
311 success=success,
442 success=success,
312 msg=msg
443 msg=msg
313 )
444 )
314 except Exception:
445 except Exception:
315 log.error(traceback.format_exc())
446 log.error(traceback.format_exc())
316 raise JSONRPCError('failed to add users group member')
447 raise JSONRPCError(
448 'failed to add member to users group `%s`' % (
449 users_group.users_group_name
450 )
451 )
317
452
318 @HasPermissionAllDecorator('hg.admin')
453 @HasPermissionAllDecorator('hg.admin')
319 def remove_user_from_users_group(self, apiuser, group_name, username):
454 def remove_user_from_users_group(self, apiuser, usersgroupid, userid):
320 """
455 """
321 Remove user from a group
456 Remove user from a group
322
457
323 :param apiuser
458 :param apiuser:
324 :param group_name
459 :param usersgroupid:
325 :param username
460 :param userid:
326 """
461 """
462 user = get_user_or_error(userid)
463 users_group = get_users_group_or_error(usersgroupid)
327
464
328 try:
465 try:
329 users_group = UsersGroup.get_by_group_name(group_name)
466 success = UsersGroupModel().remove_user_from_group(users_group,
330 if not users_group:
467 user)
331 raise JSONRPCError('unknown users group %s' % group_name)
468 msg = 'removed member `%s` from users group `%s`' % (
332
469 user.username, users_group.users_group_name
333 user = User.get_by_username(username)
470 )
334 if user is None:
335 raise JSONRPCError('unknown user %s' % username)
336
337 success = UsersGroupModel().remove_user_from_group(users_group, user)
338 msg = 'removed member %s from users group %s' % (username, group_name)
339 msg = msg if success else "User wasn't in group"
471 msg = msg if success else "User wasn't in group"
340 Session.commit()
472 Session().commit()
341 return dict(success=success, msg=msg)
473 return dict(success=success, msg=msg)
342 except Exception:
474 except Exception:
343 log.error(traceback.format_exc())
475 log.error(traceback.format_exc())
344 raise JSONRPCError('failed to remove user from group')
476 raise JSONRPCError(
477 'failed to remove member from users group `%s`' % (
478 users_group.users_group_name
479 )
480 )
345
481
346 @HasPermissionAnyDecorator('hg.admin')
482 @HasPermissionAnyDecorator('hg.admin')
347 def get_repo(self, apiuser, repoid):
483 def get_repo(self, apiuser, repoid):
@@ -349,51 +485,30 b' class ApiController(JSONRPCController):'
349 Get repository by name
485 Get repository by name
350
486
351 :param apiuser:
487 :param apiuser:
352 :param repo_name:
488 :param repoid:
353 """
489 """
354
490 repo = get_repo_or_error(repoid)
355 repo = RepoModel().get_repo(repoid)
356 if repo is None:
357 raise JSONRPCError('unknown repository %s' % repo)
358
491
359 members = []
492 members = []
360 for user in repo.repo_to_perm:
493 for user in repo.repo_to_perm:
361 perm = user.permission.permission_name
494 perm = user.permission.permission_name
362 user = user.user
495 user = user.user
363 members.append(
496 user_data = user.get_api_data()
364 dict(
497 user_data['type'] = "user"
365 type="user",
498 user_data['permission'] = perm
366 id=user.user_id,
499 members.append(user_data)
367 username=user.username,
500
368 firstname=user.name,
369 lastname=user.lastname,
370 email=user.email,
371 active=user.active,
372 admin=user.admin,
373 ldap=user.ldap_dn,
374 permission=perm
375 )
376 )
377 for users_group in repo.users_group_to_perm:
501 for users_group in repo.users_group_to_perm:
378 perm = users_group.permission.permission_name
502 perm = users_group.permission.permission_name
379 users_group = users_group.users_group
503 users_group = users_group.users_group
380 members.append(
504 users_group_data = users_group.get_api_data()
381 dict(
505 users_group_data['type'] = "users_group"
382 type="users_group",
506 users_group_data['permission'] = perm
383 id=users_group.users_group_id,
507 members.append(users_group_data)
384 name=users_group.users_group_name,
385 active=users_group.users_group_active,
386 permission=perm
387 )
388 )
389
508
390 return dict(
509 data = repo.get_api_data()
391 id=repo.repo_id,
510 data['members'] = members
392 repo_name=repo.repo_name,
511 return data
393 type=repo.repo_type,
394 description=repo.description,
395 members=members
396 )
397
512
398 @HasPermissionAnyDecorator('hg.admin')
513 @HasPermissionAnyDecorator('hg.admin')
399 def get_repos(self, apiuser):
514 def get_repos(self, apiuser):
@@ -404,19 +519,12 b' class ApiController(JSONRPCController):'
404 """
519 """
405
520
406 result = []
521 result = []
407 for repository in Repository.getAll():
522 for repo in RepoModel().get_all():
408 result.append(
523 result.append(repo.get_api_data())
409 dict(
410 id=repository.repo_id,
411 repo_name=repository.repo_name,
412 type=repository.repo_type,
413 description=repository.description
414 )
415 )
416 return result
524 return result
417
525
418 @HasPermissionAnyDecorator('hg.admin')
526 @HasPermissionAnyDecorator('hg.admin')
419 def get_repo_nodes(self, apiuser, repo_name, revision, root_path,
527 def get_repo_nodes(self, apiuser, repoid, revision, root_path,
420 ret_type='all'):
528 ret_type='all'):
421 """
529 """
422 returns a list of nodes and it's children
530 returns a list of nodes and it's children
@@ -424,13 +532,14 b' class ApiController(JSONRPCController):'
424 to show only files or dirs
532 to show only files or dirs
425
533
426 :param apiuser:
534 :param apiuser:
427 :param repo_name: name of repository
535 :param repoid: name or id of repository
428 :param revision: revision for which listing should be done
536 :param revision: revision for which listing should be done
429 :param root_path: path from which start displaying
537 :param root_path: path from which start displaying
430 :param ret_type: return type 'all|files|dirs' nodes
538 :param ret_type: return type 'all|files|dirs' nodes
431 """
539 """
540 repo = get_repo_or_error(repoid)
432 try:
541 try:
433 _d, _f = ScmModel().get_nodes(repo_name, revision, root_path,
542 _d, _f = ScmModel().get_nodes(repo, revision, root_path,
434 flat=False)
543 flat=False)
435 _map = {
544 _map = {
436 'all': _d + _f,
545 'all': _d + _f,
@@ -440,218 +549,264 b' class ApiController(JSONRPCController):'
440 return _map[ret_type]
549 return _map[ret_type]
441 except KeyError:
550 except KeyError:
442 raise JSONRPCError('ret_type must be one of %s' % _map.keys())
551 raise JSONRPCError('ret_type must be one of %s' % _map.keys())
443 except Exception, e:
552 except Exception:
444 raise JSONRPCError(e)
553 log.error(traceback.format_exc())
554 raise JSONRPCError(
555 'failed to get repo: `%s` nodes' % repo.repo_name
556 )
445
557
446 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
558 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
447 def create_repo(self, apiuser, repo_name, owner_name, description='',
559 def create_repo(self, apiuser, repo_name, owner, repo_type,
448 repo_type='hg', private=False, clone_uri=None):
560 description=Optional(''), private=Optional(False),
561 clone_uri=Optional(None), landing_rev=Optional('tip')):
449 """
562 """
450 Create repository, if clone_url is given it makes a remote clone
563 Create repository, if clone_url is given it makes a remote clone
564 if repo_name is withina group name the groups will be created
565 automatically if they aren't present
451
566
452 :param apiuser:
567 :param apiuser:
453 :param repo_name:
568 :param repo_name:
454 :param owner_name:
569 :param onwer:
570 :param repo_type:
455 :param description:
571 :param description:
456 :param repo_type:
457 :param private:
572 :param private:
458 :param clone_uri:
573 :param clone_uri:
574 :param landing_rev:
459 """
575 """
576 owner = get_user_or_error(owner)
577
578 if RepoModel().get_by_repo_name(repo_name):
579 raise JSONRPCError("repo `%s` already exist" % repo_name)
580
581 private = Optional.extract(private)
582 clone_uri = Optional.extract(clone_uri)
583 description = Optional.extract(description)
584 landing_rev = Optional.extract(landing_rev)
460
585
461 try:
586 try:
462 owner = User.get_by_username(owner_name)
587 # create structure of groups and return the last group
463 if owner is None:
464 raise JSONRPCError('unknown user %s' % owner_name)
465
466 if Repository.get_by_repo_name(repo_name):
467 raise JSONRPCError("repo %s already exist" % repo_name)
468
469 groups = repo_name.split(Repository.url_sep())
470 real_name = groups[-1]
471 # create structure of groups
472 group = map_groups(repo_name)
588 group = map_groups(repo_name)
473
589
474 repo = RepoModel().create(
590 repo = RepoModel().create_repo(
475 dict(
591 repo_name=repo_name,
476 repo_name=real_name,
592 repo_type=repo_type,
477 repo_name_full=repo_name,
593 description=description,
478 description=description,
594 owner=owner,
479 private=private,
595 private=private,
480 repo_type=repo_type,
596 clone_uri=clone_uri,
481 repo_group=group.group_id if group else None,
597 repos_group=group,
482 clone_uri=clone_uri
598 landing_rev=landing_rev,
483 ),
484 owner
485 )
599 )
486 Session.commit()
600
601 Session().commit()
487
602
488 return dict(
603 return dict(
489 id=repo.repo_id,
604 msg="Created new repository `%s`" % (repo.repo_name),
490 msg="Created new repository %s" % repo.repo_name
605 repo=repo.get_api_data()
491 )
606 )
492
607
493 except Exception:
608 except Exception:
494 log.error(traceback.format_exc())
609 log.error(traceback.format_exc())
495 raise JSONRPCError('failed to create repository %s' % repo_name)
610 raise JSONRPCError('failed to create repository `%s`' % repo_name)
496
611
497 @HasPermissionAnyDecorator('hg.admin')
612 @HasPermissionAnyDecorator('hg.admin')
498 def delete_repo(self, apiuser, repo_name):
613 def fork_repo(self, apiuser, repoid, fork_name, owner,
499 """
614 description=Optional(''), copy_permissions=Optional(False),
500 Deletes a given repository
615 private=Optional(False), landing_rev=Optional('tip')):
616 repo = get_repo_or_error(repoid)
617 repo_name = repo.repo_name
618 owner = get_user_or_error(owner)
619
620 _repo = RepoModel().get_by_repo_name(fork_name)
621 if _repo:
622 type_ = 'fork' if _repo.fork else 'repo'
623 raise JSONRPCError("%s `%s` already exist" % (type_, fork_name))
624
625 try:
626 # create structure of groups and return the last group
627 group = map_groups(fork_name)
501
628
502 :param repo_name:
629 form_data = dict(
503 """
630 repo_name=fork_name,
504 if not Repository.get_by_repo_name(repo_name):
631 repo_name_full=fork_name,
505 raise JSONRPCError("repo %s does not exist" % repo_name)
632 repo_group=group,
506 try:
633 repo_type=repo.repo_type,
507 RepoModel().delete(repo_name)
634 description=Optional.extract(description),
508 Session.commit()
635 private=Optional.extract(private),
636 copy_permissions=Optional.extract(copy_permissions),
637 landing_rev=Optional.extract(landing_rev),
638 update_after_clone=False,
639 fork_parent_id=repo.repo_id,
640 )
641 RepoModel().create_fork(form_data, cur_user=owner)
509 return dict(
642 return dict(
510 msg='Deleted repository %s' % repo_name
643 msg='Created fork of `%s` as `%s`' % (repo.repo_name,
644 fork_name),
645 success=True # cannot return the repo data here since fork
646 # cann be done async
511 )
647 )
512 except Exception:
648 except Exception:
513 log.error(traceback.format_exc())
649 log.error(traceback.format_exc())
514 raise JSONRPCError('failed to delete repository %s' % repo_name)
650 raise JSONRPCError(
651 'failed to fork repository `%s` as `%s`' % (repo_name,
652 fork_name)
653 )
515
654
516 @HasPermissionAnyDecorator('hg.admin')
655 @HasPermissionAnyDecorator('hg.admin')
517 def grant_user_permission(self, apiuser, repo_name, username, perm):
656 def delete_repo(self, apiuser, repoid):
518 """
657 """
519 Grant permission for user on given repository, or update existing one
658 Deletes a given repository
520 if found
521
659
522 :param repo_name:
660 :param apiuser:
523 :param username:
661 :param repoid:
524 :param perm:
525 """
662 """
663 repo = get_repo_or_error(repoid)
526
664
527 try:
665 try:
528 repo = Repository.get_by_repo_name(repo_name)
666 RepoModel().delete(repo)
529 if repo is None:
667 Session().commit()
530 raise JSONRPCError('unknown repository %s' % repo)
531
532 user = User.get_by_username(username)
533 if user is None:
534 raise JSONRPCError('unknown user %s' % username)
535
536 RepoModel().grant_user_permission(repo=repo, user=user, perm=perm)
537
538 Session.commit()
539 return dict(
668 return dict(
540 msg='Granted perm: %s for user: %s in repo: %s' % (
669 msg='Deleted repository `%s`' % repo.repo_name,
541 perm, username, repo_name
670 success=True
542 )
543 )
671 )
544 except Exception:
672 except Exception:
545 log.error(traceback.format_exc())
673 log.error(traceback.format_exc())
546 raise JSONRPCError(
674 raise JSONRPCError(
547 'failed to edit permission %(repo)s for %(user)s' % dict(
675 'failed to delete repository `%s`' % repo.repo_name
548 user=username, repo=repo_name
676 )
677
678 @HasPermissionAnyDecorator('hg.admin')
679 def grant_user_permission(self, apiuser, repoid, userid, perm):
680 """
681 Grant permission for user on given repository, or update existing one
682 if found
683
684 :param repoid:
685 :param userid:
686 :param perm:
687 """
688 repo = get_repo_or_error(repoid)
689 user = get_user_or_error(userid)
690 perm = get_perm_or_error(perm)
691
692 try:
693
694 RepoModel().grant_user_permission(repo=repo, user=user, perm=perm)
695
696 Session().commit()
697 return dict(
698 msg='Granted perm: `%s` for user: `%s` in repo: `%s`' % (
699 perm.permission_name, user.username, repo.repo_name
700 ),
701 success=True
702 )
703 except Exception:
704 log.error(traceback.format_exc())
705 raise JSONRPCError(
706 'failed to edit permission for user: `%s` in repo: `%s`' % (
707 userid, repoid
549 )
708 )
550 )
709 )
551
710
552 @HasPermissionAnyDecorator('hg.admin')
711 @HasPermissionAnyDecorator('hg.admin')
553 def revoke_user_permission(self, apiuser, repo_name, username):
712 def revoke_user_permission(self, apiuser, repoid, userid):
554 """
713 """
555 Revoke permission for user on given repository
714 Revoke permission for user on given repository
556
715
557 :param repo_name:
716 :param apiuser:
558 :param username:
717 :param repoid:
718 :param userid:
559 """
719 """
560
720
721 repo = get_repo_or_error(repoid)
722 user = get_user_or_error(userid)
561 try:
723 try:
562 repo = Repository.get_by_repo_name(repo_name)
724
563 if repo is None:
725 RepoModel().revoke_user_permission(repo=repo, user=user)
564 raise JSONRPCError('unknown repository %s' % repo)
565
726
566 user = User.get_by_username(username)
727 Session().commit()
567 if user is None:
568 raise JSONRPCError('unknown user %s' % username)
569
570 RepoModel().revoke_user_permission(repo=repo_name, user=username)
571
572 Session.commit()
573 return dict(
728 return dict(
574 msg='Revoked perm for user: %s in repo: %s' % (
729 msg='Revoked perm for user: `%s` in repo: `%s`' % (
575 username, repo_name
730 user.username, repo.repo_name
576 )
731 ),
732 success=True
577 )
733 )
578 except Exception:
734 except Exception:
579 log.error(traceback.format_exc())
735 log.error(traceback.format_exc())
580 raise JSONRPCError(
736 raise JSONRPCError(
581 'failed to edit permission %(repo)s for %(user)s' % dict(
737 'failed to edit permission for user: `%s` in repo: `%s`' % (
582 user=username, repo=repo_name
738 userid, repoid
583 )
739 )
584 )
740 )
585
741
586 @HasPermissionAnyDecorator('hg.admin')
742 @HasPermissionAnyDecorator('hg.admin')
587 def grant_users_group_permission(self, apiuser, repo_name, group_name, perm):
743 def grant_users_group_permission(self, apiuser, repoid, usersgroupid,
744 perm):
588 """
745 """
589 Grant permission for users group on given repository, or update
746 Grant permission for users group on given repository, or update
590 existing one if found
747 existing one if found
591
748
592 :param repo_name:
749 :param apiuser:
593 :param group_name:
750 :param repoid:
751 :param usersgroupid:
594 :param perm:
752 :param perm:
595 """
753 """
754 repo = get_repo_or_error(repoid)
755 perm = get_perm_or_error(perm)
756 users_group = get_users_group_or_error(usersgroupid)
596
757
597 try:
758 try:
598 repo = Repository.get_by_repo_name(repo_name)
759 RepoModel().grant_users_group_permission(repo=repo,
599 if repo is None:
760 group_name=users_group,
600 raise JSONRPCError('unknown repository %s' % repo)
601
602 user_group = UsersGroup.get_by_group_name(group_name)
603 if user_group is None:
604 raise JSONRPCError('unknown users group %s' % user_group)
605
606 RepoModel().grant_users_group_permission(repo=repo_name,
607 group_name=group_name,
608 perm=perm)
761 perm=perm)
609
762
610 Session.commit()
763 Session().commit()
611 return dict(
764 return dict(
612 msg='Granted perm: %s for group: %s in repo: %s' % (
765 msg='Granted perm: `%s` for users group: `%s` in '
613 perm, group_name, repo_name
766 'repo: `%s`' % (
614 )
767 perm.permission_name, users_group.users_group_name,
768 repo.repo_name
769 ),
770 success=True
615 )
771 )
616 except Exception:
772 except Exception:
773 print traceback.format_exc()
617 log.error(traceback.format_exc())
774 log.error(traceback.format_exc())
618 raise JSONRPCError(
775 raise JSONRPCError(
619 'failed to edit permission %(repo)s for %(usersgr)s' % dict(
776 'failed to edit permission for users group: `%s` in '
620 usersgr=group_name, repo=repo_name
777 'repo: `%s`' % (
778 usersgroupid, repo.repo_name
621 )
779 )
622 )
780 )
623
781
624 @HasPermissionAnyDecorator('hg.admin')
782 @HasPermissionAnyDecorator('hg.admin')
625 def revoke_users_group_permission(self, apiuser, repo_name, group_name):
783 def revoke_users_group_permission(self, apiuser, repoid, usersgroupid):
626 """
784 """
627 Revoke permission for users group on given repository
785 Revoke permission for users group on given repository
628
786
629 :param repo_name:
787 :param apiuser:
630 :param group_name:
788 :param repoid:
789 :param usersgroupid:
631 """
790 """
791 repo = get_repo_or_error(repoid)
792 users_group = get_users_group_or_error(usersgroupid)
632
793
633 try:
794 try:
634 repo = Repository.get_by_repo_name(repo_name)
795 RepoModel().revoke_users_group_permission(repo=repo,
635 if repo is None:
796 group_name=users_group)
636 raise JSONRPCError('unknown repository %s' % repo)
637
638 user_group = UsersGroup.get_by_group_name(group_name)
639 if user_group is None:
640 raise JSONRPCError('unknown users group %s' % user_group)
641
797
642 RepoModel().revoke_users_group_permission(repo=repo_name,
798 Session().commit()
643 group_name=group_name)
644
645 Session.commit()
646 return dict(
799 return dict(
647 msg='Revoked perm for group: %s in repo: %s' % (
800 msg='Revoked perm for users group: `%s` in repo: `%s`' % (
648 group_name, repo_name
801 users_group.users_group_name, repo.repo_name
649 )
802 ),
803 success=True
650 )
804 )
651 except Exception:
805 except Exception:
652 log.error(traceback.format_exc())
806 log.error(traceback.format_exc())
653 raise JSONRPCError(
807 raise JSONRPCError(
654 'failed to edit permission %(repo)s for %(usersgr)s' % dict(
808 'failed to edit permission for users group: `%s` in '
655 usersgr=group_name, repo=repo_name
809 'repo: `%s`' % (
810 users_group.users_group_name, repo.repo_name
656 )
811 )
657 )
812 )
@@ -24,14 +24,15 b''
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 logging
26 import logging
27 import binascii
27
28
28 from pylons import tmpl_context as c
29 from pylons import tmpl_context as c
29 import binascii
30
30
31 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
31 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
32 from rhodecode.lib.base import BaseRepoController, render
32 from rhodecode.lib.base import BaseRepoController, render
33 from rhodecode.lib.compat import OrderedDict
33 from rhodecode.lib.compat import OrderedDict
34 from rhodecode.lib.utils2 import safe_unicode
34 from rhodecode.lib.utils2 import safe_unicode
35
35 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
36
37
37
38
@@ -26,7 +26,6 b''
26 import logging
26 import logging
27 import traceback
27 import traceback
28
28
29 from mercurial import graphmod
30 from pylons import request, url, session, tmpl_context as c
29 from pylons import request, url, session, tmpl_context as c
31 from pylons.controllers.util import redirect
30 from pylons.controllers.util import redirect
32 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
@@ -36,9 +35,8 b' from rhodecode.lib.auth import LoginRequ'
36 from rhodecode.lib.base import BaseRepoController, render
35 from rhodecode.lib.base import BaseRepoController, render
37 from rhodecode.lib.helpers import RepoPage
36 from rhodecode.lib.helpers import RepoPage
38 from rhodecode.lib.compat import json
37 from rhodecode.lib.compat import json
39
38 from rhodecode.lib.graphmod import _colored, _dagwalker
40 from rhodecode.lib.vcs.exceptions import RepositoryError, ChangesetDoesNotExistError
39 from rhodecode.lib.vcs.exceptions import RepositoryError, ChangesetDoesNotExistError
41 from rhodecode.model.db import Repository
42
40
43 log = logging.getLogger(__name__)
41 log = logging.getLogger(__name__)
44
42
@@ -60,13 +58,13 b' class ChangelogController(BaseRepoContro'
60 int_size = int(request.params.get('size'))
58 int_size = int(request.params.get('size'))
61 except ValueError:
59 except ValueError:
62 int_size = default
60 int_size = default
63 int_size = int_size if int_size <= limit else limit
61 c.size = max(min(int_size, limit), 1)
64 c.size = int_size
65 session['changelog_size'] = c.size
62 session['changelog_size'] = c.size
66 session.save()
63 session.save()
67 else:
64 else:
68 c.size = int(session.get('changelog_size', default))
65 c.size = int(session.get('changelog_size', default))
69
66 # min size must be 1
67 c.size = max(c.size, 1)
70 p = int(request.params.get('page', 1))
68 p = int(request.params.get('page', 1))
71 branch_name = request.params.get('branch', None)
69 branch_name = request.params.get('branch', None)
72 try:
70 try:
@@ -83,8 +81,8 b' class ChangelogController(BaseRepoContro'
83 items_per_page=c.size, branch=branch_name)
81 items_per_page=c.size, branch=branch_name)
84 collection = list(c.pagination)
82 collection = list(c.pagination)
85 page_revisions = [x.raw_id for x in collection]
83 page_revisions = [x.raw_id for x in collection]
86 c.comments = c.rhodecode_db_repo.comments(page_revisions)
84 c.comments = c.rhodecode_db_repo.get_comments(page_revisions)
87
85 c.statuses = c.rhodecode_db_repo.statuses(page_revisions)
88 except (RepositoryError, ChangesetDoesNotExistError, Exception), e:
86 except (RepositoryError, ChangesetDoesNotExistError, Exception), e:
89 log.error(traceback.format_exc())
87 log.error(traceback.format_exc())
90 h.flash(str(e), category='warning')
88 h.flash(str(e), category='warning')
@@ -118,18 +116,9 b' class ChangelogController(BaseRepoContro'
118 data = []
116 data = []
119 revs = [x.revision for x in collection]
117 revs = [x.revision for x in collection]
120
118
121 if repo.alias == 'git':
119 dag = _dagwalker(repo, revs, repo.alias)
122 for _ in revs:
120 dag = _colored(dag)
123 vtx = [0, 1]
121 for (id, type, ctx, vtx, edges) in dag:
124 edges = [[0, 0, 1]]
122 data.append(['', vtx, edges])
125 data.append(['', vtx, edges])
126
127 elif repo.alias == 'hg':
128 dag = graphmod.dagwalker(repo._repo, revs)
129 c.dag = graphmod.colored(dag, repo._repo)
130 for (id, type, ctx, vtx, edges) in c.dag:
131 if type != graphmod.CHANGESET:
132 continue
133 data.append(['', vtx, edges])
134
123
135 c.jsdata = json.dumps(data)
124 c.jsdata = json.dumps(data)
@@ -40,13 +40,17 b' from rhodecode.lib.vcs.nodes import File'
40 import rhodecode.lib.helpers as h
40 import rhodecode.lib.helpers as h
41 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
41 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
42 from rhodecode.lib.base import BaseRepoController, render
42 from rhodecode.lib.base import BaseRepoController, render
43 from rhodecode.lib.utils import EmptyChangeset
43 from rhodecode.lib.utils import action_logger
44 from rhodecode.lib.compat import OrderedDict
44 from rhodecode.lib.compat import OrderedDict
45 from rhodecode.lib import diffs
45 from rhodecode.lib import diffs
46 from rhodecode.model.db import ChangesetComment
46 from rhodecode.model.db import ChangesetComment, ChangesetStatus
47 from rhodecode.model.comment import ChangesetCommentsModel
47 from rhodecode.model.comment import ChangesetCommentsModel
48 from rhodecode.model.changeset_status import ChangesetStatusModel
48 from rhodecode.model.meta import Session
49 from rhodecode.model.meta import Session
49 from rhodecode.lib.diffs import wrapped_diff
50 from rhodecode.lib.diffs import wrapped_diff
51 from rhodecode.model.repo import RepoModel
52 from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
53 from rhodecode.lib.vcs.backends.base import EmptyChangeset
50
54
51 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
52
56
@@ -165,6 +169,9 b' class ChangesetController(BaseRepoContro'
165 def __before__(self):
169 def __before__(self):
166 super(ChangesetController, self).__before__()
170 super(ChangesetController, self).__before__()
167 c.affected_files_cut_off = 60
171 c.affected_files_cut_off = 60
172 repo_model = RepoModel()
173 c.users_array = repo_model.get_users_js()
174 c.users_groups_array = repo_model.get_users_groups_js()
168
175
169 def index(self, revision):
176 def index(self, revision):
170
177
@@ -201,18 +208,24 b' class ChangesetController(BaseRepoContro'
201
208
202 cumulative_diff = 0
209 cumulative_diff = 0
203 c.cut_off = False # defines if cut off limit is reached
210 c.cut_off = False # defines if cut off limit is reached
204
211 c.changeset_statuses = ChangesetStatus.STATUSES
205 c.comments = []
212 c.comments = []
213 c.statuses = []
206 c.inline_comments = []
214 c.inline_comments = []
207 c.inline_cnt = 0
215 c.inline_cnt = 0
208 # Iterate over ranges (default changeset view is always one changeset)
216 # Iterate over ranges (default changeset view is always one changeset)
209 for changeset in c.cs_ranges:
217 for changeset in c.cs_ranges:
218
219 c.statuses.extend([ChangesetStatusModel()\
220 .get_status(c.rhodecode_db_repo.repo_id,
221 changeset.raw_id)])
222
210 c.comments.extend(ChangesetCommentsModel()\
223 c.comments.extend(ChangesetCommentsModel()\
211 .get_comments(c.rhodecode_db_repo.repo_id,
224 .get_comments(c.rhodecode_db_repo.repo_id,
212 changeset.raw_id))
225 revision=changeset.raw_id))
213 inlines = ChangesetCommentsModel()\
226 inlines = ChangesetCommentsModel()\
214 .get_inline_comments(c.rhodecode_db_repo.repo_id,
227 .get_inline_comments(c.rhodecode_db_repo.repo_id,
215 changeset.raw_id)
228 revision=changeset.raw_id)
216 c.inline_comments.extend(inlines)
229 c.inline_comments.extend(inlines)
217 c.changes[changeset.raw_id] = []
230 c.changes[changeset.raw_id] = []
218 try:
231 try:
@@ -284,7 +297,7 b' class ChangesetController(BaseRepoContro'
284 )
297 )
285
298
286 # count inline comments
299 # count inline comments
287 for path, lines in c.inline_comments:
300 for __, lines in c.inline_comments:
288 for comments in lines.values():
301 for comments in lines.values():
289 c.inline_cnt += len(comments)
302 c.inline_cnt += len(comments)
290
303
@@ -361,15 +374,48 b' class ChangesetController(BaseRepoContro'
361
374
362 @jsonify
375 @jsonify
363 def comment(self, repo_name, revision):
376 def comment(self, repo_name, revision):
377 status = request.POST.get('changeset_status')
378 change_status = request.POST.get('change_changeset_status')
379
364 comm = ChangesetCommentsModel().create(
380 comm = ChangesetCommentsModel().create(
365 text=request.POST.get('text'),
381 text=request.POST.get('text'),
366 repo_id=c.rhodecode_db_repo.repo_id,
382 repo=c.rhodecode_db_repo.repo_id,
367 user_id=c.rhodecode_user.user_id,
383 user=c.rhodecode_user.user_id,
368 revision=revision,
384 revision=revision,
369 f_path=request.POST.get('f_path'),
385 f_path=request.POST.get('f_path'),
370 line_no=request.POST.get('line')
386 line_no=request.POST.get('line'),
387 status_change=(ChangesetStatus.get_status_lbl(status)
388 if status and change_status else None)
371 )
389 )
372 Session.commit()
390
391 # get status if set !
392 if status and change_status:
393 # if latest status was from pull request and it's closed
394 # disallow changing status !
395 # dont_allow_on_closed_pull_request = True !
396
397 try:
398 ChangesetStatusModel().set_status(
399 c.rhodecode_db_repo.repo_id,
400 status,
401 c.rhodecode_user.user_id,
402 comm,
403 revision=revision,
404 dont_allow_on_closed_pull_request=True
405 )
406 except StatusChangeOnClosedPullRequestError:
407 log.error(traceback.format_exc())
408 msg = _('Changing status on a changeset associated with'
409 'a closed pull request is not allowed')
410 h.flash(msg, category='warning')
411 return redirect(h.url('changeset_home', repo_name=repo_name,
412 revision=revision))
413 action_logger(self.rhodecode_user,
414 'user_commented_revision:%s' % revision,
415 c.rhodecode_db_repo, self.ip_addr, self.sa)
416
417 Session().commit()
418
373 if not request.environ.get('HTTP_X_PARTIAL_XHR'):
419 if not request.environ.get('HTTP_X_PARTIAL_XHR'):
374 return redirect(h.url('changeset_home', repo_name=repo_name,
420 return redirect(h.url('changeset_home', repo_name=repo_name,
375 revision=revision))
421 revision=revision))
@@ -391,7 +437,7 b' class ChangesetController(BaseRepoContro'
391 owner = lambda: co.author.user_id == c.rhodecode_user.user_id
437 owner = lambda: co.author.user_id == c.rhodecode_user.user_id
392 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
438 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
393 ChangesetCommentsModel().delete(comment=co)
439 ChangesetCommentsModel().delete(comment=co)
394 Session.commit()
440 Session().commit()
395 return True
441 return True
396 else:
442 else:
397 raise HTTPForbidden()
443 raise HTTPForbidden()
@@ -28,11 +28,12 b' import logging'
28 from pylons import url, response, tmpl_context as c
28 from pylons import url, response, tmpl_context as c
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30
30
31 from rhodecode.lib.utils2 import safe_unicode
31 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
32
33 from rhodecode.lib import helpers as h
32 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
34 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
33 from rhodecode.lib.base import BaseRepoController
35 from rhodecode.lib.base import BaseRepoController
34
36 from rhodecode.lib.diffs import DiffProcessor
35 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
36
37
37 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
38
39
@@ -49,31 +50,36 b' class FeedController(BaseRepoController)'
49 self.title = self.title = _('%s %s feed') % (c.rhodecode_name, '%s')
50 self.title = self.title = _('%s %s feed') % (c.rhodecode_name, '%s')
50 self.language = 'en-us'
51 self.language = 'en-us'
51 self.ttl = "5"
52 self.ttl = "5"
52 self.feed_nr = 10
53 self.feed_nr = 20
53
54
54 def _get_title(self, cs):
55 def _get_title(self, cs):
55 return "R%s:%s - %s" % (
56 return "%s" % (
56 cs.revision, cs.short_id, cs.message
57 h.shorter(cs.message, 160)
57 )
58 )
58
59
59 def __changes(self, cs):
60 def __changes(self, cs):
60 changes = []
61 changes = []
61
62
62 a = [safe_unicode(n.path) for n in cs.added]
63 diffprocessor = DiffProcessor(cs.diff())
63 if a:
64 stats = diffprocessor.prepare(inline_diff=False)
64 changes.append('\nA ' + '\nA '.join(a))
65 for st in stats:
65
66 st.update({'added': st['stats'][0],
66 m = [safe_unicode(n.path) for n in cs.changed]
67 'removed': st['stats'][1]})
67 if m:
68 changes.append('\n %(operation)s %(filename)s '
68 changes.append('\nM ' + '\nM '.join(m))
69 '(%(added)s lines added, %(removed)s lines removed)'
70 % st)
71 return changes
69
72
70 d = [safe_unicode(n.path) for n in cs.removed]
73 def __get_desc(self, cs):
71 if d:
74 desc_msg = []
72 changes.append('\nD ' + '\nD '.join(d))
75 desc_msg.append('%s %s %s:<br/>' % (cs.author, _('commited on'),
73
76 h.fmt_date(cs.date)))
74 changes.append('</pre>')
77 desc_msg.append('<pre>')
75
78 desc_msg.append(cs.message)
76 return ''.join(changes)
79 desc_msg.append('\n')
80 desc_msg.extend(self.__changes(cs))
81 desc_msg.append('</pre>')
82 return desc_msg
77
83
78 def atom(self, repo_name):
84 def atom(self, repo_name):
79 """Produce an atom-1.0 feed via feedgenerator module"""
85 """Produce an atom-1.0 feed via feedgenerator module"""
@@ -87,15 +93,13 b' class FeedController(BaseRepoController)'
87 )
93 )
88
94
89 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
95 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
90 desc_msg = []
91 desc_msg.append('%s - %s<br/><pre>' % (cs.author, cs.date))
92 desc_msg.append(self.__changes(cs))
93
94 feed.add_item(title=self._get_title(cs),
96 feed.add_item(title=self._get_title(cs),
95 link=url('changeset_home', repo_name=repo_name,
97 link=url('changeset_home', repo_name=repo_name,
96 revision=cs.raw_id, qualified=True),
98 revision=cs.raw_id, qualified=True),
97 author_name=cs.author,
99 author_name=cs.author,
98 description=''.join(desc_msg))
100 description=''.join(self.__get_desc(cs)),
101 pubdate=cs.date,
102 )
99
103
100 response.content_type = feed.mime_type
104 response.content_type = feed.mime_type
101 return feed.writeString('utf-8')
105 return feed.writeString('utf-8')
@@ -112,15 +116,12 b' class FeedController(BaseRepoController)'
112 )
116 )
113
117
114 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
118 for cs in reversed(list(c.rhodecode_repo[-self.feed_nr:])):
115 desc_msg = []
116 desc_msg.append('%s - %s<br/><pre>' % (cs.author, cs.date))
117 desc_msg.append(self.__changes(cs))
118
119 feed.add_item(title=self._get_title(cs),
119 feed.add_item(title=self._get_title(cs),
120 link=url('changeset_home', repo_name=repo_name,
120 link=url('changeset_home', repo_name=repo_name,
121 revision=cs.raw_id, qualified=True),
121 revision=cs.raw_id, qualified=True),
122 author_name=cs.author,
122 author_name=cs.author,
123 description=''.join(desc_msg),
123 description=''.join(self.__get_desc(cs)),
124 pubdate=cs.date,
124 )
125 )
125
126
126 response.content_type = feed.mime_type
127 response.content_type = feed.mime_type
@@ -32,7 +32,6 b' from pylons import request, response, tm'
32 from pylons.i18n.translation import _
32 from pylons.i18n.translation import _
33 from pylons.controllers.util import redirect
33 from pylons.controllers.util import redirect
34 from pylons.decorators import jsonify
34 from pylons.decorators import jsonify
35 from paste.fileapp import FileApp, _FileIter
36
35
37 from rhodecode.lib import diffs
36 from rhodecode.lib import diffs
38 from rhodecode.lib import helpers as h
37 from rhodecode.lib import helpers as h
@@ -41,7 +40,7 b' from rhodecode.lib.compat import Ordered'
41 from rhodecode.lib.utils2 import convert_line_endings, detect_mode, safe_str
40 from rhodecode.lib.utils2 import convert_line_endings, detect_mode, safe_str
42 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
41 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
43 from rhodecode.lib.base import BaseRepoController, render
42 from rhodecode.lib.base import BaseRepoController, render
44 from rhodecode.lib.utils import EmptyChangeset
43 from rhodecode.lib.vcs.backends.base import EmptyChangeset
45 from rhodecode.lib.vcs.conf import settings
44 from rhodecode.lib.vcs.conf import settings
46 from rhodecode.lib.vcs.exceptions import RepositoryError, \
45 from rhodecode.lib.vcs.exceptions import RepositoryError, \
47 ChangesetDoesNotExistError, EmptyRepositoryError, \
46 ChangesetDoesNotExistError, EmptyRepositoryError, \
@@ -61,7 +60,6 b' log = logging.getLogger(__name__)'
61
60
62 class FilesController(BaseRepoController):
61 class FilesController(BaseRepoController):
63
62
64 @LoginRequired()
65 def __before__(self):
63 def __before__(self):
66 super(FilesController, self).__before__()
64 super(FilesController, self).__before__()
67 c.cut_off_limit = self.cut_off_limit
65 c.cut_off_limit = self.cut_off_limit
@@ -83,8 +81,8 b' class FilesController(BaseRepoController'
83 url_ = url('files_add_home',
81 url_ = url('files_add_home',
84 repo_name=c.repo_name,
82 repo_name=c.repo_name,
85 revision=0, f_path='')
83 revision=0, f_path='')
86 add_new = '<a href="%s">[%s]</a>' % (url_, _('add new'))
84 add_new = '<a href="%s">[%s]</a>' % (url_, _('click here to add new file'))
87 h.flash(h.literal(_('There are no files yet %s' % add_new)),
85 h.flash(h.literal(_('There are no files yet %s') % add_new),
88 category='warning')
86 category='warning')
89 redirect(h.url('summary_home', repo_name=repo_name))
87 redirect(h.url('summary_home', repo_name=repo_name))
90
88
@@ -113,6 +111,7 b' class FilesController(BaseRepoController'
113
111
114 return file_node
112 return file_node
115
113
114 @LoginRequired()
116 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
115 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
117 'repository.admin')
116 'repository.admin')
118 def index(self, repo_name, revision, f_path, annotate=False):
117 def index(self, repo_name, revision, f_path, annotate=False):
@@ -154,16 +153,25 b' class FilesController(BaseRepoController'
154 c.file = c.changeset.get_node(f_path)
153 c.file = c.changeset.get_node(f_path)
155
154
156 if c.file.is_file():
155 if c.file.is_file():
157 c.file_history = self._get_node_history(c.changeset, f_path)
156 _hist = c.changeset.get_file_history(f_path)
157 c.file_history = self._get_node_history(c.changeset, f_path,
158 _hist)
159 c.authors = []
160 for a in set([x.author for x in _hist]):
161 c.authors.append((h.email(a), h.person(a)))
158 else:
162 else:
159 c.file_history = []
163 c.authors = c.file_history = []
160 except RepositoryError, e:
164 except RepositoryError, e:
161 h.flash(str(e), category='warning')
165 h.flash(str(e), category='warning')
162 redirect(h.url('files_home', repo_name=repo_name,
166 redirect(h.url('files_home', repo_name=repo_name,
163 revision=revision))
167 revision='tip'))
168
169 if request.environ.get('HTTP_X_PARTIAL_XHR'):
170 return render('files/files_ypjax.html')
164
171
165 return render('files/files.html')
172 return render('files/files.html')
166
173
174 @LoginRequired()
167 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
175 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
168 'repository.admin')
176 'repository.admin')
169 def rawfile(self, repo_name, revision, f_path):
177 def rawfile(self, repo_name, revision, f_path):
@@ -176,6 +184,7 b' class FilesController(BaseRepoController'
176 response.content_type = file_node.mimetype
184 response.content_type = file_node.mimetype
177 return file_node.content
185 return file_node.content
178
186
187 @LoginRequired()
179 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
188 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
180 'repository.admin')
189 'repository.admin')
181 def raw(self, repo_name, revision, f_path):
190 def raw(self, repo_name, revision, f_path):
@@ -222,8 +231,18 b' class FilesController(BaseRepoController'
222 response.content_type = mimetype
231 response.content_type = mimetype
223 return file_node.content
232 return file_node.content
224
233
234 @LoginRequired()
225 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
235 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
226 def edit(self, repo_name, revision, f_path):
236 def edit(self, repo_name, revision, f_path):
237 repo = Repository.get_by_repo_name(repo_name)
238 if repo.enable_locking and repo.locked[0]:
239 h.flash(_('This repository is has been locked by %s on %s')
240 % (h.person_by_id(repo.locked[0]),
241 h.fmt_date(h.time_to_datetime(repo.locked[1]))),
242 'warning')
243 return redirect(h.url('files_home',
244 repo_name=repo_name, revision='tip'))
245
227 r_post = request.POST
246 r_post = request.POST
228
247
229 c.cs = self.__get_cs_or_redirect(revision, repo_name)
248 c.cs = self.__get_cs_or_redirect(revision, repo_name)
@@ -260,7 +279,7 b' class FilesController(BaseRepoController'
260 user=self.rhodecode_user,
279 user=self.rhodecode_user,
261 author=author, message=message,
280 author=author, message=message,
262 content=content, f_path=f_path)
281 content=content, f_path=f_path)
263 h.flash(_('Successfully committed to %s' % f_path),
282 h.flash(_('Successfully committed to %s') % f_path,
264 category='success')
283 category='success')
265
284
266 except Exception:
285 except Exception:
@@ -271,8 +290,19 b' class FilesController(BaseRepoController'
271
290
272 return render('files/files_edit.html')
291 return render('files/files_edit.html')
273
292
293 @LoginRequired()
274 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
294 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
275 def add(self, repo_name, revision, f_path):
295 def add(self, repo_name, revision, f_path):
296
297 repo = Repository.get_by_repo_name(repo_name)
298 if repo.enable_locking and repo.locked[0]:
299 h.flash(_('This repository is has been locked by %s on %s')
300 % (h.person_by_id(repo.locked[0]),
301 h.fmt_date(h.time_to_datetime(repo.locked[1]))),
302 'warning')
303 return redirect(h.url('files_home',
304 repo_name=repo_name, revision='tip'))
305
276 r_post = request.POST
306 r_post = request.POST
277 c.cs = self.__get_cs_or_redirect(revision, repo_name,
307 c.cs = self.__get_cs_or_redirect(revision, repo_name,
278 redirect_after=False)
308 redirect_after=False)
@@ -313,7 +343,7 b' class FilesController(BaseRepoController'
313 user=self.rhodecode_user,
343 user=self.rhodecode_user,
314 author=author, message=message,
344 author=author, message=message,
315 content=content, f_path=node_path)
345 content=content, f_path=node_path)
316 h.flash(_('Successfully committed to %s' % node_path),
346 h.flash(_('Successfully committed to %s') % node_path,
317 category='success')
347 category='success')
318 except NodeAlreadyExistsError, e:
348 except NodeAlreadyExistsError, e:
319 h.flash(_(e), category='error')
349 h.flash(_(e), category='error')
@@ -325,6 +355,7 b' class FilesController(BaseRepoController'
325
355
326 return render('files/files_add.html')
356 return render('files/files_add.html')
327
357
358 @LoginRequired()
328 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
359 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
329 'repository.admin')
360 'repository.admin')
330 def archivefile(self, repo_name, fname):
361 def archivefile(self, repo_name, fname):
@@ -361,27 +392,28 b' class FilesController(BaseRepoController'
361 except (ImproperArchiveTypeError, KeyError):
392 except (ImproperArchiveTypeError, KeyError):
362 return _('Unknown archive type')
393 return _('Unknown archive type')
363
394
364 fd, _archive_name = tempfile.mkstemp(suffix='rcarchive')
395 fd, archive = tempfile.mkstemp()
365 with open(_archive_name, 'wb') as f:
396 t = open(archive, 'wb')
366 cs.fill_archive(stream=f, kind=fileformat, subrepos=subrepos)
397 cs.fill_archive(stream=t, kind=fileformat, subrepos=subrepos)
367
398 t.close()
368 content_disposition = 'attachment; filename=%s-%s%s' \
369 % (repo_name, revision[:12], ext)
370 content_length = os.path.getsize(_archive_name)
371
399
372 headers = [('Content-Disposition', str(content_disposition)),
400 def get_chunked_archive(archive):
373 ('Content-Type', str(content_type)),
401 stream = open(archive, 'rb')
374 ('Content-Length', str(content_length))]
402 while True:
403 data = stream.read(16 * 1024)
404 if not data:
405 stream.close()
406 os.close(fd)
407 os.remove(archive)
408 break
409 yield data
375
410
376 class _DestroyingFileWrapper(_FileIter):
411 response.content_disposition = str('attachment; filename=%s-%s%s' \
377 def close(self):
412 % (repo_name, revision[:12], ext))
378 self.file.close
413 response.content_type = str(content_type)
379 os.remove(self.file.name)
414 return get_chunked_archive(archive)
380
415
381 request.environ['wsgi.file_wrapper'] = _DestroyingFileWrapper
416 @LoginRequired()
382 fapp = FileApp(_archive_name, headers=headers)
383 return fapp(request.environ, self.start_response)
384
385 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
417 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
386 'repository.admin')
418 'repository.admin')
387 def diff(self, repo_name, f_path):
419 def diff(self, repo_name, f_path):
@@ -454,8 +486,9 b' class FilesController(BaseRepoController'
454
486
455 return render('files/file_diff.html')
487 return render('files/file_diff.html')
456
488
457 def _get_node_history(self, cs, f_path):
489 def _get_node_history(self, cs, f_path, changesets=None):
458 changesets = cs.get_file_history(f_path)
490 if changesets is None:
491 changesets = cs.get_file_history(f_path)
459 hist_l = []
492 hist_l = []
460
493
461 changesets_group = ([], _("Changesets"))
494 changesets_group = ([], _("Changesets"))
@@ -479,12 +512,13 b' class FilesController(BaseRepoController'
479
512
480 return hist_l
513 return hist_l
481
514
482 @jsonify
515 @LoginRequired()
483 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
516 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
484 'repository.admin')
517 'repository.admin')
518 @jsonify
485 def nodelist(self, repo_name, revision, f_path):
519 def nodelist(self, repo_name, revision, f_path):
486 if request.environ.get('HTTP_X_PARTIAL_XHR'):
520 if request.environ.get('HTTP_X_PARTIAL_XHR'):
487 cs = self.__get_cs_or_redirect(revision, repo_name)
521 cs = self.__get_cs_or_redirect(revision, repo_name)
488 _d, _f = ScmModel().get_nodes(repo_name, cs.raw_id, f_path,
522 _d, _f = ScmModel().get_nodes(repo_name, cs.raw_id, f_path,
489 flat=False)
523 flat=False)
490 return _d + _f
524 return {'nodes': _d + _f}
@@ -35,11 +35,13 b' import rhodecode.lib.helpers as h'
35
35
36 from rhodecode.lib.helpers import Page
36 from rhodecode.lib.helpers import Page
37 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator, \
37 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator, \
38 NotAnonymous, HasRepoPermissionAny
38 NotAnonymous, HasRepoPermissionAny, HasPermissionAllDecorator,\
39 HasPermissionAnyDecorator
39 from rhodecode.lib.base import BaseRepoController, render
40 from rhodecode.lib.base import BaseRepoController, render
40 from rhodecode.model.db import Repository, RepoGroup, UserFollowing, User
41 from rhodecode.model.db import Repository, RepoGroup, UserFollowing, User
41 from rhodecode.model.repo import RepoModel
42 from rhodecode.model.repo import RepoModel
42 from rhodecode.model.forms import RepoForkForm
43 from rhodecode.model.forms import RepoForkForm
44 from rhodecode.model.scm import ScmModel
43
45
44 log = logging.getLogger(__name__)
46 log = logging.getLogger(__name__)
45
47
@@ -53,6 +55,8 b' class ForksController(BaseRepoController'
53 def __load_defaults(self):
55 def __load_defaults(self):
54 c.repo_groups = RepoGroup.groups_choices()
56 c.repo_groups = RepoGroup.groups_choices()
55 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
57 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
58 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
59 c.landing_revs_choices = choices
56
60
57 def __load_data(self, repo_name=None):
61 def __load_data(self, repo_name=None):
58 """
62 """
@@ -120,6 +124,7 b' class ForksController(BaseRepoController'
120 return render('/forks/forks.html')
124 return render('/forks/forks.html')
121
125
122 @NotAnonymous()
126 @NotAnonymous()
127 @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
123 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
128 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
124 'repository.admin')
129 'repository.admin')
125 def fork(self, repo_name):
130 def fork(self, repo_name):
@@ -142,24 +147,23 b' class ForksController(BaseRepoController'
142 force_defaults=False
147 force_defaults=False
143 )
148 )
144
149
145
146 @NotAnonymous()
150 @NotAnonymous()
151 @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
147 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
152 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
148 'repository.admin')
153 'repository.admin')
149 def fork_create(self, repo_name):
154 def fork_create(self, repo_name):
150 self.__load_defaults()
155 self.__load_defaults()
151 c.repo_info = Repository.get_by_repo_name(repo_name)
156 c.repo_info = Repository.get_by_repo_name(repo_name)
152 _form = RepoForkForm(old_data={'repo_type': c.repo_info.repo_type},
157 _form = RepoForkForm(old_data={'repo_type': c.repo_info.repo_type},
153 repo_groups=c.repo_groups_choices,)()
158 repo_groups=c.repo_groups_choices,
159 landing_revs=c.landing_revs_choices)()
154 form_result = {}
160 form_result = {}
155 try:
161 try:
156 form_result = _form.to_python(dict(request.POST))
162 form_result = _form.to_python(dict(request.POST))
157 # add org_path of repo so we can do a clone from it later
158 form_result['org_path'] = c.repo_info.repo_name
159
163
160 # create fork is done sometimes async on celery, db transaction
164 # create fork is done sometimes async on celery, db transaction
161 # management is handled there.
165 # management is handled there.
162 RepoModel().create_fork(form_result, self.rhodecode_user)
166 RepoModel().create_fork(form_result, self.rhodecode_user.user_id)
163 h.flash(_('forked %s repository as %s') \
167 h.flash(_('forked %s repository as %s') \
164 % (repo_name, form_result['repo_name']),
168 % (repo_name, form_result['repo_name']),
165 category='success')
169 category='success')
@@ -26,7 +26,7 b''
26 import logging
26 import logging
27
27
28 from pylons import tmpl_context as c, request
28 from pylons import tmpl_context as c, request
29 from paste.httpexceptions import HTTPBadRequest
29 from webob.exc import HTTPBadRequest
30
30
31 from rhodecode.lib.auth import LoginRequired
31 from rhodecode.lib.auth import LoginRequired
32 from rhodecode.lib.base import BaseController, render
32 from rhodecode.lib.base import BaseController, render
@@ -51,7 +51,8 b' class HomeController(BaseController):'
51 if request.is_xhr:
51 if request.is_xhr:
52 all_repos = Repository.query().order_by(Repository.repo_name).all()
52 all_repos = Repository.query().order_by(Repository.repo_name).all()
53 c.repos_list = self.scm_model.get_repos(all_repos,
53 c.repos_list = self.scm_model.get_repos(all_repos,
54 sort_key='name_sort')
54 sort_key='name_sort',
55 simple=True)
55 return render('/repo_switcher_list.html')
56 return render('/repo_switcher_list.html')
56 else:
57 else:
57 return HTTPBadRequest()
58 return HTTPBadRequest()
@@ -30,7 +30,7 b' from sqlalchemy.orm import joinedload'
30 from webhelpers.paginate import Page
30 from webhelpers.paginate import Page
31 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
31 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
32
32
33 from paste.httpexceptions import HTTPBadRequest
33 from webob.exc import HTTPBadRequest
34 from pylons import request, tmpl_context as c, response, url
34 from pylons import request, tmpl_context as c, response, url
35 from pylons.i18n.translation import _
35 from pylons.i18n.translation import _
36
36
@@ -49,8 +49,6 b' class JournalController(BaseController):'
49
49
50 def __before__(self):
50 def __before__(self):
51 super(JournalController, self).__before__()
51 super(JournalController, self).__before__()
52 self.rhodecode_user = self.rhodecode_user
53 self.title = _('%s public journal %s feed') % (c.rhodecode_name, '%s')
54 self.language = 'en-us'
52 self.language = 'en-us'
55 self.ttl = "5"
53 self.ttl = "5"
56 self.feed_nr = 20
54 self.feed_nr = 20
@@ -84,6 +82,30 b' class JournalController(BaseController):'
84 return c.journal_data
82 return c.journal_data
85 return render('journal/journal.html')
83 return render('journal/journal.html')
86
84
85 @LoginRequired(api_access=True)
86 @NotAnonymous()
87 def journal_atom(self):
88 """
89 Produce an atom-1.0 feed via feedgenerator module
90 """
91 following = self.sa.query(UserFollowing)\
92 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
93 .options(joinedload(UserFollowing.follows_repository))\
94 .all()
95 return self._atom_feed(following, public=False)
96
97 @LoginRequired(api_access=True)
98 @NotAnonymous()
99 def journal_rss(self):
100 """
101 Produce an rss feed via feedgenerator module
102 """
103 following = self.sa.query(UserFollowing)\
104 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
105 .options(joinedload(UserFollowing.follows_repository))\
106 .all()
107 return self._rss_feed(following, public=False)
108
87 def _get_daily_aggregate(self, journal):
109 def _get_daily_aggregate(self, journal):
88 groups = []
110 groups = []
89 for k, g in groupby(journal, lambda x: x.action_as_day):
111 for k, g in groupby(journal, lambda x: x.action_as_day):
@@ -173,6 +195,80 b' class JournalController(BaseController):'
173 return c.journal_data
195 return c.journal_data
174 return render('journal/public_journal.html')
196 return render('journal/public_journal.html')
175
197
198 def _atom_feed(self, repos, public=True):
199 journal = self._get_journal_data(repos)
200 if public:
201 _link = url('public_journal_atom', qualified=True)
202 _desc = '%s %s %s' % (c.rhodecode_name, _('public journal'),
203 'atom feed')
204 else:
205 _link = url('journal_atom', qualified=True)
206 _desc = '%s %s %s' % (c.rhodecode_name, _('journal'), 'atom feed')
207
208 feed = Atom1Feed(title=_desc,
209 link=_link,
210 description=_desc,
211 language=self.language,
212 ttl=self.ttl)
213
214 for entry in journal[:self.feed_nr]:
215 action, action_extra, ico = h.action_parser(entry, feed=True)
216 title = "%s - %s %s" % (entry.user.short_contact, action(),
217 entry.repository.repo_name)
218 desc = action_extra()
219 _url = None
220 if entry.repository is not None:
221 _url = url('changelog_home',
222 repo_name=entry.repository.repo_name,
223 qualified=True)
224
225 feed.add_item(title=title,
226 pubdate=entry.action_date,
227 link=_url or url('', qualified=True),
228 author_email=entry.user.email,
229 author_name=entry.user.full_contact,
230 description=desc)
231
232 response.content_type = feed.mime_type
233 return feed.writeString('utf-8')
234
235 def _rss_feed(self, repos, public=True):
236 journal = self._get_journal_data(repos)
237 if public:
238 _link = url('public_journal_atom', qualified=True)
239 _desc = '%s %s %s' % (c.rhodecode_name, _('public journal'),
240 'rss feed')
241 else:
242 _link = url('journal_atom', qualified=True)
243 _desc = '%s %s %s' % (c.rhodecode_name, _('journal'), 'rss feed')
244
245 feed = Rss201rev2Feed(title=_desc,
246 link=_link,
247 description=_desc,
248 language=self.language,
249 ttl=self.ttl)
250
251 for entry in journal[:self.feed_nr]:
252 action, action_extra, ico = h.action_parser(entry, feed=True)
253 title = "%s - %s %s" % (entry.user.short_contact, action(),
254 entry.repository.repo_name)
255 desc = action_extra()
256 _url = None
257 if entry.repository is not None:
258 _url = url('changelog_home',
259 repo_name=entry.repository.repo_name,
260 qualified=True)
261
262 feed.add_item(title=title,
263 pubdate=entry.action_date,
264 link=_url or url('', qualified=True),
265 author_email=entry.user.email,
266 author_name=entry.user.full_contact,
267 description=desc)
268
269 response.content_type = feed.mime_type
270 return feed.writeString('utf-8')
271
176 @LoginRequired(api_access=True)
272 @LoginRequired(api_access=True)
177 def public_journal_atom(self):
273 def public_journal_atom(self):
178 """
274 """
@@ -183,29 +279,7 b' class JournalController(BaseController):'
183 .options(joinedload(UserFollowing.follows_repository))\
279 .options(joinedload(UserFollowing.follows_repository))\
184 .all()
280 .all()
185
281
186 journal = self._get_journal_data(c.following)
282 return self._atom_feed(c.following)
187
188 feed = Atom1Feed(title=self.title % 'atom',
189 link=url('public_journal_atom', qualified=True),
190 description=_('Public journal'),
191 language=self.language,
192 ttl=self.ttl)
193
194 for entry in journal[:self.feed_nr]:
195 #tmpl = h.action_parser(entry)[0]
196 action, action_extra = h.action_parser(entry, feed=True)
197 title = "%s - %s %s" % (entry.user.short_contact, action,
198 entry.repository.repo_name)
199 desc = action_extra()
200 feed.add_item(title=title,
201 pubdate=entry.action_date,
202 link=url('', qualified=True),
203 author_email=entry.user.email,
204 author_name=entry.user.full_contact,
205 description=desc)
206
207 response.content_type = feed.mime_type
208 return feed.writeString('utf-8')
209
283
210 @LoginRequired(api_access=True)
284 @LoginRequired(api_access=True)
211 def public_journal_rss(self):
285 def public_journal_rss(self):
@@ -217,26 +291,4 b' class JournalController(BaseController):'
217 .options(joinedload(UserFollowing.follows_repository))\
291 .options(joinedload(UserFollowing.follows_repository))\
218 .all()
292 .all()
219
293
220 journal = self._get_journal_data(c.following)
294 return self._rss_feed(c.following)
221
222 feed = Rss201rev2Feed(title=self.title % 'rss',
223 link=url('public_journal_rss', qualified=True),
224 description=_('Public journal'),
225 language=self.language,
226 ttl=self.ttl)
227
228 for entry in journal[:self.feed_nr]:
229 #tmpl = h.action_parser(entry)[0]
230 action, action_extra = h.action_parser(entry, feed=True)
231 title = "%s - %s %s" % (entry.user.short_contact, action,
232 entry.repository.repo_name)
233 desc = action_extra()
234 feed.add_item(title=title,
235 pubdate=entry.action_date,
236 link=url('', qualified=True),
237 author_email=entry.user.email,
238 author_name=entry.user.full_contact,
239 description=desc)
240
241 response.content_type = feed.mime_type
242 return feed.writeString('utf-8')
@@ -25,9 +25,11 b''
25
25
26 import logging
26 import logging
27 import formencode
27 import formencode
28 import datetime
29 import urlparse
28
30
29 from formencode import htmlfill
31 from formencode import htmlfill
30
32 from webob.exc import HTTPFound
31 from pylons.i18n.translation import _
33 from pylons.i18n.translation import _
32 from pylons.controllers.util import abort, redirect
34 from pylons.controllers.util import abort, redirect
33 from pylons import request, response, session, tmpl_context as c, url
35 from pylons import request, response, session, tmpl_context as c, url
@@ -51,7 +53,7 b' class LoginController(BaseController):'
51
53
52 def index(self):
54 def index(self):
53 # redirect if already logged in
55 # redirect if already logged in
54 c.came_from = request.GET.get('came_from', None)
56 c.came_from = request.GET.get('came_from')
55
57
56 if self.rhodecode_user.is_authenticated \
58 if self.rhodecode_user.is_authenticated \
57 and self.rhodecode_user.username != 'default':
59 and self.rhodecode_user.username != 'default':
@@ -62,6 +64,7 b' class LoginController(BaseController):'
62 # import Login Form validator class
64 # import Login Form validator class
63 login_form = LoginForm()
65 login_form = LoginForm()
64 try:
66 try:
67 session.invalidate()
65 c.form_result = login_form.to_python(dict(request.POST))
68 c.form_result = login_form.to_python(dict(request.POST))
66 # form checks for username/password, now we're authenticated
69 # form checks for username/password, now we're authenticated
67 username = c.form_result['username']
70 username = c.form_result['username']
@@ -70,22 +73,46 b' class LoginController(BaseController):'
70 auth_user.set_authenticated()
73 auth_user.set_authenticated()
71 cs = auth_user.get_cookie_store()
74 cs = auth_user.get_cookie_store()
72 session['rhodecode_user'] = cs
75 session['rhodecode_user'] = cs
76 user.update_lastlogin()
77 Session().commit()
78
73 # If they want to be remembered, update the cookie
79 # If they want to be remembered, update the cookie
74 if c.form_result['remember'] is not False:
80 if c.form_result['remember'] is not False:
75 session.cookie_expires = False
81 _year = (datetime.datetime.now() +
76 session._set_cookie_values()
82 datetime.timedelta(seconds=60 * 60 * 24 * 365))
77 session._update_cookie_out()
83 session._set_cookie_expires(_year)
84
78 session.save()
85 session.save()
79
86
80 log.info('user %s is now authenticated and stored in '
87 log.info('user %s is now authenticated and stored in '
81 'session, session attrs %s' % (username, cs))
88 'session, session attrs %s' % (username, cs))
82 user.update_lastlogin()
89
83 Session.commit()
90 # dumps session attrs back to cookie
91 session._update_cookie_out()
84
92
93 # we set new cookie
94 headers = None
95 if session.request['set_cookie']:
96 # send set-cookie headers back to response to update cookie
97 headers = [('Set-Cookie', session.request['cookie_out'])]
98
99 allowed_schemes = ['http', 'https']
85 if c.came_from:
100 if c.came_from:
86 return redirect(c.came_from)
101 parsed = urlparse.urlparse(c.came_from)
102 server_parsed = urlparse.urlparse(url.current())
103 if parsed.scheme and parsed.scheme not in allowed_schemes:
104 log.error(
105 'Suspicious URL scheme detected %s for url %s' %
106 (parsed.scheme, parsed))
107 c.came_from = url('home')
108 elif server_parsed.netloc != parsed.netloc:
109 log.error('Suspicious NETLOC detected %s for url %s'
110 'server url is: %s' %
111 (parsed.netloc, parsed, server_parsed))
112 c.came_from = url('home')
113 raise HTTPFound(location=c.came_from, headers=headers)
87 else:
114 else:
88 return redirect(url('home'))
115 raise HTTPFound(location=url('home'), headers=headers)
89
116
90 except formencode.Invalid, errors:
117 except formencode.Invalid, errors:
91 return htmlfill.render(
118 return htmlfill.render(
@@ -115,7 +142,7 b' class LoginController(BaseController):'
115 UserModel().create_registration(form_result)
142 UserModel().create_registration(form_result)
116 h.flash(_('You have successfully registered into rhodecode'),
143 h.flash(_('You have successfully registered into rhodecode'),
117 category='success')
144 category='success')
118 Session.commit()
145 Session().commit()
119 return redirect(url('login_home'))
146 return redirect(url('login_home'))
120
147
121 except formencode.Invalid, errors:
148 except formencode.Invalid, errors:
@@ -3,7 +3,7 b''
3 rhodecode.controllers.search
3 rhodecode.controllers.search
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Search controller for rhodecode
6 Search controller for RhodeCode
7
7
8 :created_on: Aug 7, 2010
8 :created_on: Aug 7, 2010
9 :author: marcink
9 :author: marcink
@@ -30,7 +30,8 b' from pylons import request, config, tmpl'
30
30
31 from rhodecode.lib.auth import LoginRequired
31 from rhodecode.lib.auth import LoginRequired
32 from rhodecode.lib.base import BaseController, render
32 from rhodecode.lib.base import BaseController, render
33 from rhodecode.lib.indexers import SCHEMA, IDX_NAME, ResultWrapper
33 from rhodecode.lib.indexers import CHGSETS_SCHEMA, SCHEMA, CHGSET_IDX_NAME, \
34 IDX_NAME, WhooshResultWrapper
34
35
35 from webhelpers.paginate import Page
36 from webhelpers.paginate import Page
36 from webhelpers.util import update_params
37 from webhelpers.util import update_params
@@ -38,6 +39,7 b' from webhelpers.util import update_param'
38 from whoosh.index import open_dir, EmptyIndexError
39 from whoosh.index import open_dir, EmptyIndexError
39 from whoosh.qparser import QueryParser, QueryParserError
40 from whoosh.qparser import QueryParser, QueryParserError
40 from whoosh.query import Phrase, Wildcard, Term, Prefix
41 from whoosh.query import Phrase, Wildcard, Term, Prefix
42 from rhodecode.model.repo import RepoModel
41
43
42 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
43
45
@@ -53,25 +55,41 b' class SearchController(BaseController):'
53 c.formated_results = []
55 c.formated_results = []
54 c.runtime = ''
56 c.runtime = ''
55 c.cur_query = request.GET.get('q', None)
57 c.cur_query = request.GET.get('q', None)
56 c.cur_type = request.GET.get('type', 'source')
58 c.cur_type = request.GET.get('type', 'content')
57 c.cur_search = search_type = {'content': 'content',
59 c.cur_search = search_type = {'content': 'content',
58 'commit': 'content',
60 'commit': 'message',
59 'path': 'path',
61 'path': 'path',
60 'repository': 'repository'}\
62 'repository': 'repository'
61 .get(c.cur_type, 'content')
63 }.get(c.cur_type, 'content')
64
65 index_name = {
66 'content': IDX_NAME,
67 'commit': CHGSET_IDX_NAME,
68 'path': IDX_NAME
69 }.get(c.cur_type, IDX_NAME)
70
71 schema_defn = {
72 'content': SCHEMA,
73 'commit': CHGSETS_SCHEMA,
74 'path': SCHEMA
75 }.get(c.cur_type, SCHEMA)
76
77 log.debug('IDX: %s' % index_name)
78 log.debug('SCHEMA: %s' % schema_defn)
62
79
63 if c.cur_query:
80 if c.cur_query:
64 cur_query = c.cur_query.lower()
81 cur_query = c.cur_query.lower()
82 log.debug(cur_query)
65
83
66 if c.cur_query:
84 if c.cur_query:
67 p = int(request.params.get('page', 1))
85 p = int(request.params.get('page', 1))
68 highlight_items = set()
86 highlight_items = set()
69 try:
87 try:
70 idx = open_dir(config['app_conf']['index_dir'],
88 idx = open_dir(config['app_conf']['index_dir'],
71 indexname=IDX_NAME)
89 indexname=index_name)
72 searcher = idx.searcher()
90 searcher = idx.searcher()
73
91
74 qp = QueryParser(search_type, schema=SCHEMA)
92 qp = QueryParser(search_type, schema=schema_defn)
75 if c.repo_name:
93 if c.repo_name:
76 cur_query = u'repository:%s %s' % (c.repo_name, cur_query)
94 cur_query = u'repository:%s %s' % (c.repo_name, cur_query)
77 try:
95 try:
@@ -83,13 +101,13 b' class SearchController(BaseController):'
83 highlight_items.add(query.text)
101 highlight_items.add(query.text)
84 else:
102 else:
85 for i in query.all_terms():
103 for i in query.all_terms():
86 if i[0] == 'content':
104 if i[0] in ['content', 'message']:
87 highlight_items.add(i[1])
105 highlight_items.add(i[1])
88
106
89 matcher = query.matcher(searcher)
107 matcher = query.matcher(searcher)
90
108
91 log.debug(query)
109 log.debug('query: %s' % query)
92 log.debug(highlight_items)
110 log.debug('hl terms: %s' % highlight_items)
93 results = searcher.search(query)
111 results = searcher.search(query)
94 res_ln = len(results)
112 res_ln = len(results)
95 c.runtime = '%s results (%.3f seconds)' % (
113 c.runtime = '%s results (%.3f seconds)' % (
@@ -98,11 +116,11 b' class SearchController(BaseController):'
98
116
99 def url_generator(**kw):
117 def url_generator(**kw):
100 return update_params("?q=%s&type=%s" \
118 return update_params("?q=%s&type=%s" \
101 % (c.cur_query, c.cur_search), **kw)
119 % (c.cur_query, c.cur_type), **kw)
102
120 repo_location = RepoModel().repos_path
103 c.formated_results = Page(
121 c.formated_results = Page(
104 ResultWrapper(search_type, searcher, matcher,
122 WhooshResultWrapper(search_type, searcher, matcher,
105 highlight_items),
123 highlight_items, repo_location),
106 page=p,
124 page=p,
107 item_count=res_ln,
125 item_count=res_ln,
108 items_per_page=10,
126 items_per_page=10,
@@ -121,6 +139,5 b' class SearchController(BaseController):'
121 log.error(traceback.format_exc())
139 log.error(traceback.format_exc())
122 c.runtime = _('An error occurred during this search operation')
140 c.runtime = _('An error occurred during this search operation')
123
141
124
125 # Return a rendered template
142 # Return a rendered template
126 return render('/search/search.html')
143 return render('/search/search.html')
@@ -43,6 +43,7 b' from rhodecode.model.forms import RepoSe'
43 from rhodecode.model.repo import RepoModel
43 from rhodecode.model.repo import RepoModel
44 from rhodecode.model.db import RepoGroup
44 from rhodecode.model.db import RepoGroup
45 from rhodecode.model.meta import Session
45 from rhodecode.model.meta import Session
46 from rhodecode.model.scm import ScmModel
46
47
47 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
48
49
@@ -60,6 +61,8 b' class SettingsController(BaseRepoControl'
60 repo_model = RepoModel()
61 repo_model = RepoModel()
61 c.users_array = repo_model.get_users_js()
62 c.users_array = repo_model.get_users_js()
62 c.users_groups_array = repo_model.get_users_groups_js()
63 c.users_groups_array = repo_model.get_users_groups_js()
64 choices, c.landing_revs = ScmModel().get_repo_landing_revs()
65 c.landing_revs_choices = choices
63
66
64 @HasRepoPermissionAllDecorator('repository.admin')
67 @HasRepoPermissionAllDecorator('repository.admin')
65 def index(self, repo_name):
68 def index(self, repo_name):
@@ -94,17 +97,18 b' class SettingsController(BaseRepoControl'
94
97
95 _form = RepoSettingsForm(edit=True,
98 _form = RepoSettingsForm(edit=True,
96 old_data={'repo_name': repo_name},
99 old_data={'repo_name': repo_name},
97 repo_groups=c.repo_groups_choices)()
100 repo_groups=c.repo_groups_choices,
101 landing_revs=c.landing_revs_choices)()
98 try:
102 try:
99 form_result = _form.to_python(dict(request.POST))
103 form_result = _form.to_python(dict(request.POST))
100
104
101 repo_model.update(repo_name, form_result)
105 repo_model.update(repo_name, form_result)
102 invalidate_cache('get_repo_cached_%s' % repo_name)
106 invalidate_cache('get_repo_cached_%s' % repo_name)
103 h.flash(_('Repository %s updated successfully' % repo_name),
107 h.flash(_('Repository %s updated successfully') % repo_name,
104 category='success')
108 category='success')
105 changed_name = form_result['repo_name_full']
109 changed_name = form_result['repo_name_full']
106 action_logger(self.rhodecode_user, 'user_updated_repo',
110 action_logger(self.rhodecode_user, 'user_updated_repo',
107 changed_name, '', self.sa)
111 changed_name, self.ip_addr, self.sa)
108 Session.commit()
112 Session.commit()
109 except formencode.Invalid, errors:
113 except formencode.Invalid, errors:
110 c.repo_info = repo_model.get_by_repo_name(repo_name)
114 c.repo_info = repo_model.get_by_repo_name(repo_name)
@@ -145,7 +149,7 b' class SettingsController(BaseRepoControl'
145 return redirect(url('home'))
149 return redirect(url('home'))
146 try:
150 try:
147 action_logger(self.rhodecode_user, 'user_deleted_repo',
151 action_logger(self.rhodecode_user, 'user_deleted_repo',
148 repo_name, '', self.sa)
152 repo_name, self.ip_addr, self.sa)
149 repo_model.delete(repo)
153 repo_model.delete(repo)
150 invalidate_cache('get_repo_cached_%s' % repo_name)
154 invalidate_cache('get_repo_cached_%s' % repo_name)
151 h.flash(_('deleted repository %s') % repo_name, category='success')
155 h.flash(_('deleted repository %s') % repo_name, category='success')
@@ -45,12 +45,13 b' from rhodecode.model.db import Statistic'
45 from rhodecode.lib.utils2 import safe_unicode
45 from rhodecode.lib.utils2 import safe_unicode
46 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
46 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
47 from rhodecode.lib.base import BaseRepoController, render
47 from rhodecode.lib.base import BaseRepoController, render
48 from rhodecode.lib.utils import EmptyChangeset
48 from rhodecode.lib.vcs.backends.base import EmptyChangeset
49 from rhodecode.lib.markup_renderer import MarkupRenderer
49 from rhodecode.lib.markup_renderer import MarkupRenderer
50 from rhodecode.lib.celerylib import run_task
50 from rhodecode.lib.celerylib import run_task
51 from rhodecode.lib.celerylib.tasks import get_commits_stats
51 from rhodecode.lib.celerylib.tasks import get_commits_stats
52 from rhodecode.lib.helpers import RepoPage
52 from rhodecode.lib.helpers import RepoPage
53 from rhodecode.lib.compat import json, OrderedDict
53 from rhodecode.lib.compat import json, OrderedDict
54 from rhodecode.lib.vcs.nodes import FileNode
54
55
55 log = logging.getLogger(__name__)
56 log = logging.getLogger(__name__)
56
57
@@ -179,27 +180,31 b' class SummaryController(BaseRepoControll'
179 if c.enable_downloads:
180 if c.enable_downloads:
180 c.download_options = self._get_download_links(c.rhodecode_repo)
181 c.download_options = self._get_download_links(c.rhodecode_repo)
181
182
182 c.readme_data, c.readme_file = self.__get_readme_data(
183 c.readme_data, c.readme_file = \
183 c.rhodecode_db_repo.repo_name, c.rhodecode_repo
184 self.__get_readme_data(c.rhodecode_db_repo)
184 )
185 return render('summary/summary.html')
185 return render('summary/summary.html')
186
186
187 def __get_readme_data(self, repo_name, repo):
187 def __get_readme_data(self, db_repo):
188 repo_name = db_repo.repo_name
188
189
189 @cache_region('long_term')
190 @cache_region('long_term')
190 def _get_readme_from_cache(key):
191 def _get_readme_from_cache(key):
191 readme_data = None
192 readme_data = None
192 readme_file = None
193 readme_file = None
193 log.debug('Fetching readme file')
194 log.debug('Looking for README file')
194 try:
195 try:
195 cs = repo.get_changeset() # fetches TIP
196 # get's the landing revision! or tip if fails
197 cs = db_repo.get_landing_changeset()
196 renderer = MarkupRenderer()
198 renderer = MarkupRenderer()
197 for f in README_FILES:
199 for f in README_FILES:
198 try:
200 try:
199 readme = cs.get_node(f)
201 readme = cs.get_node(f)
202 if not isinstance(readme, FileNode):
203 continue
200 readme_file = f
204 readme_file = f
205 log.debug('Found README file `%s` rendering...' %
206 readme_file)
201 readme_data = renderer.render(readme.content, f)
207 readme_data = renderer.render(readme.content, f)
202 log.debug('Found readme %s' % readme_file)
203 break
208 break
204 except NodeDoesNotExistError:
209 except NodeDoesNotExistError:
205 continue
210 continue
This diff has been collapsed as it changes many lines, (3687 lines changed) Show them Hide them
@@ -7,7 +7,7 b' msgid ""'
7 msgstr ""
7 msgstr ""
8 "Project-Id-Version: rhodecode 0.1\n"
8 "Project-Id-Version: rhodecode 0.1\n"
9 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
9 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
10 "POT-Creation-Date: 2011-09-14 15:50-0300\n"
10 "POT-Creation-Date: 2012-09-02 20:30+0200\n"
11 "PO-Revision-Date: 2011-02-25 19:13+0100\n"
11 "PO-Revision-Date: 2011-02-25 19:13+0100\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13 "Language-Team: en <LL@li.org>\n"
13 "Language-Team: en <LL@li.org>\n"
@@ -17,20 +17,36 b' msgstr ""'
17 "Content-Transfer-Encoding: 8bit\n"
17 "Content-Transfer-Encoding: 8bit\n"
18 "Generated-By: Babel 0.9.6\n"
18 "Generated-By: Babel 0.9.6\n"
19
19
20 #: rhodecode/controllers/changeset.py:108
20 #: rhodecode/controllers/changelog.py:94
21 #: rhodecode/controllers/changeset.py:149
21 msgid "All Branches"
22 #: rhodecode/controllers/changeset.py:216
22 msgstr ""
23 #: rhodecode/controllers/changeset.py:229
23
24 #: rhodecode/controllers/changeset.py:83
25 msgid "show white space"
26 msgstr ""
27
28 #: rhodecode/controllers/changeset.py:90 rhodecode/controllers/changeset.py:97
29 msgid "ignore white space"
30 msgstr ""
31
32 #: rhodecode/controllers/changeset.py:157
33 #, python-format
34 msgid "%s line context"
35 msgstr ""
36
37 #: rhodecode/controllers/changeset.py:333
38 #: rhodecode/controllers/changeset.py:348 rhodecode/lib/diffs.py:70
24 msgid "binary file"
39 msgid "binary file"
25 msgstr ""
40 msgstr ""
26
41
27 #: rhodecode/controllers/changeset.py:123
42 #: rhodecode/controllers/changeset.py:408
28 #: rhodecode/controllers/changeset.py:168
43 msgid ""
29 msgid "Changeset is to big and was cut off, see raw changeset instead"
44 "Changing status on a changeset associated witha closed pull request is "
30 msgstr ""
45 "not allowed"
31
46 msgstr ""
32 #: rhodecode/controllers/changeset.py:159
47
33 msgid "Diff is to big and was cut off, see raw diff instead"
48 #: rhodecode/controllers/compare.py:69
49 msgid "There are no changesets yet"
34 msgstr ""
50 msgstr ""
35
51
36 #: rhodecode/controllers/error.py:69
52 #: rhodecode/controllers/error.py:69
@@ -59,117 +75,107 b' msgid ""'
59 "fulfilling the request."
75 "fulfilling the request."
60 msgstr ""
76 msgstr ""
61
77
62 #: rhodecode/controllers/feed.py:48
78 #: rhodecode/controllers/feed.py:49
63 #, python-format
79 #, python-format
64 msgid "Changes on %s repository"
80 msgid "Changes on %s repository"
65 msgstr ""
81 msgstr ""
66
82
67 #: rhodecode/controllers/feed.py:49
83 #: rhodecode/controllers/feed.py:50
68 #, python-format
84 #, python-format
69 msgid "%s %s feed"
85 msgid "%s %s feed"
70 msgstr ""
86 msgstr ""
71
87
72 #: rhodecode/controllers/files.py:72
88 #: rhodecode/controllers/feed.py:75
73 msgid "There are no files yet"
89 msgid "commited on"
74 msgstr ""
90 msgstr ""
75
91
76 #: rhodecode/controllers/files.py:262
92 #: rhodecode/controllers/files.py:84
93 msgid "click here to add new file"
94 msgstr ""
95
96 #: rhodecode/controllers/files.py:85
97 #, python-format
98 msgid "There are no files yet %s"
99 msgstr ""
100
101 #: rhodecode/controllers/files.py:239 rhodecode/controllers/files.py:299
102 #, python-format
103 msgid "This repository is has been locked by %s on %s"
104 msgstr ""
105
106 #: rhodecode/controllers/files.py:266
77 #, python-format
107 #, python-format
78 msgid "Edited %s via RhodeCode"
108 msgid "Edited %s via RhodeCode"
79 msgstr ""
109 msgstr ""
80
110
81 #: rhodecode/controllers/files.py:267
111 #: rhodecode/controllers/files.py:271
82 #: rhodecode/templates/files/file_diff.html:40
83 msgid "No changes"
112 msgid "No changes"
84 msgstr ""
113 msgstr ""
85
114
86 #: rhodecode/controllers/files.py:278
115 #: rhodecode/controllers/files.py:282 rhodecode/controllers/files.py:346
87 #, python-format
116 #, python-format
88 msgid "Successfully committed to %s"
117 msgid "Successfully committed to %s"
89 msgstr ""
118 msgstr ""
90
119
91 #: rhodecode/controllers/files.py:283
120 #: rhodecode/controllers/files.py:287 rhodecode/controllers/files.py:352
92 msgid "Error occurred during commit"
121 msgid "Error occurred during commit"
93 msgstr ""
122 msgstr ""
94
123
95 #: rhodecode/controllers/files.py:308
124 #: rhodecode/controllers/files.py:318
125 #, python-format
126 msgid "Added %s via RhodeCode"
127 msgstr ""
128
129 #: rhodecode/controllers/files.py:332
130 msgid "No content"
131 msgstr ""
132
133 #: rhodecode/controllers/files.py:336
134 msgid "No filename"
135 msgstr ""
136
137 #: rhodecode/controllers/files.py:378
96 msgid "downloads disabled"
138 msgid "downloads disabled"
97 msgstr ""
139 msgstr ""
98
140
99 #: rhodecode/controllers/files.py:313
141 #: rhodecode/controllers/files.py:389
100 #, python-format
142 #, python-format
101 msgid "Unknown revision %s"
143 msgid "Unknown revision %s"
102 msgstr ""
144 msgstr ""
103
145
104 #: rhodecode/controllers/files.py:315
146 #: rhodecode/controllers/files.py:391
105 msgid "Empty repository"
147 msgid "Empty repository"
106 msgstr ""
148 msgstr ""
107
149
108 #: rhodecode/controllers/files.py:317
150 #: rhodecode/controllers/files.py:393
109 msgid "Unknown archive type"
151 msgid "Unknown archive type"
110 msgstr ""
152 msgstr ""
111
153
112 #: rhodecode/controllers/files.py:385 rhodecode/controllers/files.py:398
154 #: rhodecode/controllers/files.py:494
113 msgid "Binary file"
155 #: rhodecode/templates/changeset/changeset_range.html:13
114 msgstr ""
156 #: rhodecode/templates/changeset/changeset_range.html:31
115
116 #: rhodecode/controllers/files.py:417
117 #: rhodecode/templates/changeset/changeset_range.html:4
118 #: rhodecode/templates/changeset/changeset_range.html:12
119 #: rhodecode/templates/changeset/changeset_range.html:29
120 msgid "Changesets"
157 msgid "Changesets"
121 msgstr ""
158 msgstr ""
122
159
123 #: rhodecode/controllers/files.py:418 rhodecode/controllers/summary.py:175
160 #: rhodecode/controllers/files.py:495 rhodecode/controllers/pullrequests.py:72
124 #: rhodecode/templates/branches/branches.html:5
161 #: rhodecode/controllers/summary.py:232 rhodecode/model/scm.py:543
125 #: rhodecode/templates/summary/summary.html:690
126 msgid "Branches"
162 msgid "Branches"
127 msgstr ""
163 msgstr ""
128
164
129 #: rhodecode/controllers/files.py:419 rhodecode/controllers/summary.py:176
165 #: rhodecode/controllers/files.py:496 rhodecode/controllers/pullrequests.py:76
130 #: rhodecode/templates/summary/summary.html:679
166 #: rhodecode/controllers/summary.py:233 rhodecode/model/scm.py:554
131 #: rhodecode/templates/tags/tags.html:5
132 msgid "Tags"
167 msgid "Tags"
133 msgstr ""
168 msgstr ""
134
169
135 #: rhodecode/controllers/journal.py:50
170 #: rhodecode/controllers/forks.py:73 rhodecode/controllers/admin/repos.py:90
136 #, python-format
171 #, python-format
137 msgid "%s public journal %s feed"
138 msgstr ""
139
140 #: rhodecode/controllers/journal.py:178 rhodecode/controllers/journal.py:212
141 #: rhodecode/templates/admin/repos/repo_edit.html:171
142 #: rhodecode/templates/base/base.html:50
143 msgid "Public journal"
144 msgstr ""
145
146 #: rhodecode/controllers/login.py:111
147 msgid "You have successfully registered into rhodecode"
148 msgstr ""
149
150 #: rhodecode/controllers/login.py:133
151 msgid "Your password reset link was sent"
152 msgstr ""
153
154 #: rhodecode/controllers/login.py:155
155 msgid ""
172 msgid ""
156 "Your password reset was successful, new password has been sent to your "
173 "%s repository is not mapped to db perhaps it was created or renamed from "
157 "email"
174 "the filesystem please run the application again in order to rescan "
158 msgstr ""
175 "repositories"
159
176 msgstr ""
160 #: rhodecode/controllers/search.py:109
177
161 msgid "Invalid search query. Try quoting it."
178 #: rhodecode/controllers/forks.py:133 rhodecode/controllers/settings.py:72
162 msgstr ""
163
164 #: rhodecode/controllers/search.py:114
165 msgid "There is no index to search in. Please run whoosh indexer"
166 msgstr ""
167
168 #: rhodecode/controllers/search.py:118
169 msgid "An error occurred during this search operation"
170 msgstr ""
171
172 #: rhodecode/controllers/settings.py:61 rhodecode/controllers/settings.py:171
173 #, python-format
179 #, python-format
174 msgid ""
180 msgid ""
175 "%s repository is not mapped to db perhaps it was created or renamed from "
181 "%s repository is not mapped to db perhaps it was created or renamed from "
@@ -177,20 +183,89 b' msgid ""'
177 "repositories"
183 "repositories"
178 msgstr ""
184 msgstr ""
179
185
180 #: rhodecode/controllers/settings.py:109
186 #: rhodecode/controllers/forks.py:167
181 #: rhodecode/controllers/admin/repos.py:239
187 #, python-format
188 msgid "forked %s repository as %s"
189 msgstr ""
190
191 #: rhodecode/controllers/forks.py:181
192 #, python-format
193 msgid "An error occurred during repository forking %s"
194 msgstr ""
195
196 #: rhodecode/controllers/journal.py:202 rhodecode/controllers/journal.py:239
197 msgid "public journal"
198 msgstr ""
199
200 #: rhodecode/controllers/journal.py:206 rhodecode/controllers/journal.py:243
201 #: rhodecode/templates/base/base.html:220
202 msgid "journal"
203 msgstr ""
204
205 #: rhodecode/controllers/login.py:143
206 msgid "You have successfully registered into rhodecode"
207 msgstr ""
208
209 #: rhodecode/controllers/login.py:164
210 msgid "Your password reset link was sent"
211 msgstr ""
212
213 #: rhodecode/controllers/login.py:184
214 msgid ""
215 "Your password reset was successful, new password has been sent to your "
216 "email"
217 msgstr ""
218
219 #: rhodecode/controllers/pullrequests.py:74 rhodecode/model/scm.py:549
220 msgid "Bookmarks"
221 msgstr ""
222
223 #: rhodecode/controllers/pullrequests.py:158
224 msgid "Pull request requires a title with min. 3 chars"
225 msgstr ""
226
227 #: rhodecode/controllers/pullrequests.py:160
228 msgid "error during creation of pull request"
229 msgstr ""
230
231 #: rhodecode/controllers/pullrequests.py:181
232 msgid "Successfully opened new pull request"
233 msgstr ""
234
235 #: rhodecode/controllers/pullrequests.py:184
236 msgid "Error occurred during sending pull request"
237 msgstr ""
238
239 #: rhodecode/controllers/pullrequests.py:217
240 msgid "Successfully deleted pull request"
241 msgstr ""
242
243 #: rhodecode/controllers/search.py:131
244 msgid "Invalid search query. Try quoting it."
245 msgstr ""
246
247 #: rhodecode/controllers/search.py:136
248 msgid "There is no index to search in. Please run whoosh indexer"
249 msgstr ""
250
251 #: rhodecode/controllers/search.py:140
252 msgid "An error occurred during this search operation"
253 msgstr ""
254
255 #: rhodecode/controllers/settings.py:107
256 #: rhodecode/controllers/admin/repos.py:266
182 #, python-format
257 #, python-format
183 msgid "Repository %s updated successfully"
258 msgid "Repository %s updated successfully"
184 msgstr ""
259 msgstr ""
185
260
186 #: rhodecode/controllers/settings.py:126
261 #: rhodecode/controllers/settings.py:125
187 #: rhodecode/controllers/admin/repos.py:257
262 #: rhodecode/controllers/admin/repos.py:284
188 #, python-format
263 #, python-format
189 msgid "error occurred during update of repository %s"
264 msgid "error occurred during update of repository %s"
190 msgstr ""
265 msgstr ""
191
266
192 #: rhodecode/controllers/settings.py:144
267 #: rhodecode/controllers/settings.py:143
193 #: rhodecode/controllers/admin/repos.py:275
268 #: rhodecode/controllers/admin/repos.py:302
194 #, python-format
269 #, python-format
195 msgid ""
270 msgid ""
196 "%s repository is not mapped to db perhaps it was moved or renamed from "
271 "%s repository is not mapped to db perhaps it was moved or renamed from "
@@ -198,111 +273,102 b' msgid ""'
198 "repositories"
273 "repositories"
199 msgstr ""
274 msgstr ""
200
275
201 #: rhodecode/controllers/settings.py:156
276 #: rhodecode/controllers/settings.py:155
202 #: rhodecode/controllers/admin/repos.py:287
277 #: rhodecode/controllers/admin/repos.py:314
203 #, python-format
278 #, python-format
204 msgid "deleted repository %s"
279 msgid "deleted repository %s"
205 msgstr ""
280 msgstr ""
206
281
207 #: rhodecode/controllers/settings.py:159
282 #: rhodecode/controllers/settings.py:159
208 #: rhodecode/controllers/admin/repos.py:297
283 #: rhodecode/controllers/admin/repos.py:324
209 #: rhodecode/controllers/admin/repos.py:303
284 #: rhodecode/controllers/admin/repos.py:330
210 #, python-format
285 #, python-format
211 msgid "An error occurred during deletion of %s"
286 msgid "An error occurred during deletion of %s"
212 msgstr ""
287 msgstr ""
213
288
214 #: rhodecode/controllers/settings.py:193
289 #: rhodecode/controllers/summary.py:138
215 #, python-format
216 msgid "forked %s repository as %s"
217 msgstr ""
218
219 #: rhodecode/controllers/settings.py:211
220 #, python-format
221 msgid "An error occurred during repository forking %s"
222 msgstr ""
223
224 #: rhodecode/controllers/summary.py:123
225 msgid "No data loaded yet"
290 msgid "No data loaded yet"
226 msgstr ""
291 msgstr ""
227
292
228 #: rhodecode/controllers/summary.py:126
293 #: rhodecode/controllers/summary.py:142
294 #: rhodecode/templates/summary/summary.html:148
229 msgid "Statistics are disabled for this repository"
295 msgid "Statistics are disabled for this repository"
230 msgstr ""
296 msgstr ""
231
297
232 #: rhodecode/controllers/admin/ldap_settings.py:49
233 msgid "BASE"
234 msgstr ""
235
236 #: rhodecode/controllers/admin/ldap_settings.py:50
298 #: rhodecode/controllers/admin/ldap_settings.py:50
237 msgid "ONELEVEL"
299 msgid "BASE"
238 msgstr ""
300 msgstr ""
239
301
240 #: rhodecode/controllers/admin/ldap_settings.py:51
302 #: rhodecode/controllers/admin/ldap_settings.py:51
303 msgid "ONELEVEL"
304 msgstr ""
305
306 #: rhodecode/controllers/admin/ldap_settings.py:52
241 msgid "SUBTREE"
307 msgid "SUBTREE"
242 msgstr ""
308 msgstr ""
243
309
244 #: rhodecode/controllers/admin/ldap_settings.py:55
245 msgid "NEVER"
246 msgstr ""
247
248 #: rhodecode/controllers/admin/ldap_settings.py:56
310 #: rhodecode/controllers/admin/ldap_settings.py:56
249 msgid "ALLOW"
311 msgid "NEVER"
250 msgstr ""
312 msgstr ""
251
313
252 #: rhodecode/controllers/admin/ldap_settings.py:57
314 #: rhodecode/controllers/admin/ldap_settings.py:57
253 msgid "TRY"
315 msgid "ALLOW"
254 msgstr ""
316 msgstr ""
255
317
256 #: rhodecode/controllers/admin/ldap_settings.py:58
318 #: rhodecode/controllers/admin/ldap_settings.py:58
257 msgid "DEMAND"
319 msgid "TRY"
258 msgstr ""
320 msgstr ""
259
321
260 #: rhodecode/controllers/admin/ldap_settings.py:59
322 #: rhodecode/controllers/admin/ldap_settings.py:59
323 msgid "DEMAND"
324 msgstr ""
325
326 #: rhodecode/controllers/admin/ldap_settings.py:60
261 msgid "HARD"
327 msgid "HARD"
262 msgstr ""
328 msgstr ""
263
329
264 #: rhodecode/controllers/admin/ldap_settings.py:63
265 msgid "No encryption"
266 msgstr ""
267
268 #: rhodecode/controllers/admin/ldap_settings.py:64
330 #: rhodecode/controllers/admin/ldap_settings.py:64
269 msgid "LDAPS connection"
331 msgid "No encryption"
270 msgstr ""
332 msgstr ""
271
333
272 #: rhodecode/controllers/admin/ldap_settings.py:65
334 #: rhodecode/controllers/admin/ldap_settings.py:65
335 msgid "LDAPS connection"
336 msgstr ""
337
338 #: rhodecode/controllers/admin/ldap_settings.py:66
273 msgid "START_TLS on LDAP connection"
339 msgid "START_TLS on LDAP connection"
274 msgstr ""
340 msgstr ""
275
341
276 #: rhodecode/controllers/admin/ldap_settings.py:115
342 #: rhodecode/controllers/admin/ldap_settings.py:126
277 msgid "Ldap settings updated successfully"
343 msgid "Ldap settings updated successfully"
278 msgstr ""
344 msgstr ""
279
345
280 #: rhodecode/controllers/admin/ldap_settings.py:120
346 #: rhodecode/controllers/admin/ldap_settings.py:130
281 msgid "Unable to activate ldap. The \"python-ldap\" library is missing."
347 msgid "Unable to activate ldap. The \"python-ldap\" library is missing."
282 msgstr ""
348 msgstr ""
283
349
284 #: rhodecode/controllers/admin/ldap_settings.py:134
350 #: rhodecode/controllers/admin/ldap_settings.py:147
285 msgid "error occurred during update of ldap settings"
351 msgid "error occurred during update of ldap settings"
286 msgstr ""
352 msgstr ""
287
353
288 #: rhodecode/controllers/admin/permissions.py:56
289 msgid "None"
290 msgstr ""
291
292 #: rhodecode/controllers/admin/permissions.py:57
293 msgid "Read"
294 msgstr ""
295
296 #: rhodecode/controllers/admin/permissions.py:58
297 msgid "Write"
298 msgstr ""
299
300 #: rhodecode/controllers/admin/permissions.py:59
354 #: rhodecode/controllers/admin/permissions.py:59
355 msgid "None"
356 msgstr ""
357
358 #: rhodecode/controllers/admin/permissions.py:60
359 msgid "Read"
360 msgstr ""
361
362 #: rhodecode/controllers/admin/permissions.py:61
363 msgid "Write"
364 msgstr ""
365
366 #: rhodecode/controllers/admin/permissions.py:62
301 #: rhodecode/templates/admin/ldap/ldap.html:9
367 #: rhodecode/templates/admin/ldap/ldap.html:9
302 #: rhodecode/templates/admin/permissions/permissions.html:9
368 #: rhodecode/templates/admin/permissions/permissions.html:9
303 #: rhodecode/templates/admin/repos/repo_add.html:9
369 #: rhodecode/templates/admin/repos/repo_add.html:9
304 #: rhodecode/templates/admin/repos/repo_edit.html:9
370 #: rhodecode/templates/admin/repos/repo_edit.html:9
305 #: rhodecode/templates/admin/repos/repos.html:10
371 #: rhodecode/templates/admin/repos/repos.html:9
306 #: rhodecode/templates/admin/repos_groups/repos_groups_add.html:8
372 #: rhodecode/templates/admin/repos_groups/repos_groups_add.html:8
307 #: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:8
373 #: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:8
308 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:10
374 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:10
@@ -310,550 +376,871 b' msgstr ""'
310 #: rhodecode/templates/admin/settings/settings.html:9
376 #: rhodecode/templates/admin/settings/settings.html:9
311 #: rhodecode/templates/admin/users/user_add.html:8
377 #: rhodecode/templates/admin/users/user_add.html:8
312 #: rhodecode/templates/admin/users/user_edit.html:9
378 #: rhodecode/templates/admin/users/user_edit.html:9
313 #: rhodecode/templates/admin/users/user_edit.html:110
379 #: rhodecode/templates/admin/users/user_edit.html:122
314 #: rhodecode/templates/admin/users/users.html:9
380 #: rhodecode/templates/admin/users/users.html:9
315 #: rhodecode/templates/admin/users_groups/users_group_add.html:8
381 #: rhodecode/templates/admin/users_groups/users_group_add.html:8
316 #: rhodecode/templates/admin/users_groups/users_group_edit.html:9
382 #: rhodecode/templates/admin/users_groups/users_group_edit.html:9
317 #: rhodecode/templates/admin/users_groups/users_groups.html:9
383 #: rhodecode/templates/admin/users_groups/users_groups.html:9
318 #: rhodecode/templates/base/base.html:279
384 #: rhodecode/templates/base/base.html:197
319 #: rhodecode/templates/base/base.html:366
385 #: rhodecode/templates/base/base.html:337
320 #: rhodecode/templates/base/base.html:368
386 #: rhodecode/templates/base/base.html:339
321 #: rhodecode/templates/base/base.html:370
387 #: rhodecode/templates/base/base.html:341
322 msgid "Admin"
388 msgid "Admin"
323 msgstr ""
389 msgstr ""
324
390
325 #: rhodecode/controllers/admin/permissions.py:62
391 #: rhodecode/controllers/admin/permissions.py:65
326 msgid "disabled"
392 msgid "disabled"
327 msgstr ""
393 msgstr ""
328
394
329 #: rhodecode/controllers/admin/permissions.py:64
395 #: rhodecode/controllers/admin/permissions.py:67
330 msgid "allowed with manual account activation"
396 msgid "allowed with manual account activation"
331 msgstr ""
397 msgstr ""
332
398
333 #: rhodecode/controllers/admin/permissions.py:66
334 msgid "allowed with automatic account activation"
335 msgstr ""
336
337 #: rhodecode/controllers/admin/permissions.py:68
338 msgid "Disabled"
339 msgstr ""
340
341 #: rhodecode/controllers/admin/permissions.py:69
399 #: rhodecode/controllers/admin/permissions.py:69
400 msgid "allowed with automatic account activation"
401 msgstr ""
402
403 #: rhodecode/controllers/admin/permissions.py:71
404 #: rhodecode/controllers/admin/permissions.py:74
405 msgid "Disabled"
406 msgstr ""
407
408 #: rhodecode/controllers/admin/permissions.py:72
409 #: rhodecode/controllers/admin/permissions.py:75
342 msgid "Enabled"
410 msgid "Enabled"
343 msgstr ""
411 msgstr ""
344
412
345 #: rhodecode/controllers/admin/permissions.py:102
413 #: rhodecode/controllers/admin/permissions.py:116
346 msgid "Default permissions updated successfully"
414 msgid "Default permissions updated successfully"
347 msgstr ""
415 msgstr ""
348
416
349 #: rhodecode/controllers/admin/permissions.py:119
417 #: rhodecode/controllers/admin/permissions.py:130
350 msgid "error occurred during update of permissions"
418 msgid "error occurred during update of permissions"
351 msgstr ""
419 msgstr ""
352
420
353 #: rhodecode/controllers/admin/repos.py:96
421 #: rhodecode/controllers/admin/repos.py:123
354 #, python-format
422 msgid "--REMOVE FORK--"
355 msgid ""
423 msgstr ""
356 "%s repository is not mapped to db perhaps it was created or renamed from "
424
357 "the filesystem please run the application again in order to rescan "
425 #: rhodecode/controllers/admin/repos.py:192
358 "repositories"
359 msgstr ""
360
361 #: rhodecode/controllers/admin/repos.py:172
362 #, python-format
426 #, python-format
363 msgid "created repository %s from %s"
427 msgid "created repository %s from %s"
364 msgstr ""
428 msgstr ""
365
429
366 #: rhodecode/controllers/admin/repos.py:176
430 #: rhodecode/controllers/admin/repos.py:196
367 #, python-format
431 #, python-format
368 msgid "created repository %s"
432 msgid "created repository %s"
369 msgstr ""
433 msgstr ""
370
434
371 #: rhodecode/controllers/admin/repos.py:205
435 #: rhodecode/controllers/admin/repos.py:227
372 #, python-format
436 #, python-format
373 msgid "error occurred during creation of repository %s"
437 msgid "error occurred during creation of repository %s"
374 msgstr ""
438 msgstr ""
375
439
376 #: rhodecode/controllers/admin/repos.py:292
440 #: rhodecode/controllers/admin/repos.py:319
377 #, python-format
441 #, python-format
378 msgid "Cannot delete %s it still contains attached forks"
442 msgid "Cannot delete %s it still contains attached forks"
379 msgstr ""
443 msgstr ""
380
444
381 #: rhodecode/controllers/admin/repos.py:320
445 #: rhodecode/controllers/admin/repos.py:348
382 msgid "An error occurred during deletion of repository user"
446 msgid "An error occurred during deletion of repository user"
383 msgstr ""
447 msgstr ""
384
448
385 #: rhodecode/controllers/admin/repos.py:335
386 msgid "An error occurred during deletion of repository users groups"
387 msgstr ""
388
389 #: rhodecode/controllers/admin/repos.py:352
390 msgid "An error occurred during deletion of repository stats"
391 msgstr ""
392
393 #: rhodecode/controllers/admin/repos.py:367
449 #: rhodecode/controllers/admin/repos.py:367
450 msgid "An error occurred during deletion of repository users groups"
451 msgstr ""
452
453 #: rhodecode/controllers/admin/repos.py:385
454 msgid "An error occurred during deletion of repository stats"
455 msgstr ""
456
457 #: rhodecode/controllers/admin/repos.py:402
394 msgid "An error occurred during cache invalidation"
458 msgid "An error occurred during cache invalidation"
395 msgstr ""
459 msgstr ""
396
460
397 #: rhodecode/controllers/admin/repos.py:387
461 #: rhodecode/controllers/admin/repos.py:422
462 msgid "An error occurred during unlocking"
463 msgstr ""
464
465 #: rhodecode/controllers/admin/repos.py:442
398 msgid "Updated repository visibility in public journal"
466 msgid "Updated repository visibility in public journal"
399 msgstr ""
467 msgstr ""
400
468
401 #: rhodecode/controllers/admin/repos.py:390
469 #: rhodecode/controllers/admin/repos.py:446
402 msgid "An error occurred during setting this repository in public journal"
470 msgid "An error occurred during setting this repository in public journal"
403 msgstr ""
471 msgstr ""
404
472
405 #: rhodecode/controllers/admin/repos.py:395 rhodecode/model/forms.py:53
473 #: rhodecode/controllers/admin/repos.py:451 rhodecode/model/validators.py:299
406 msgid "Token mismatch"
474 msgid "Token mismatch"
407 msgstr ""
475 msgstr ""
408
476
409 #: rhodecode/controllers/admin/repos.py:408
477 #: rhodecode/controllers/admin/repos.py:464
410 msgid "Pulled from remote location"
478 msgid "Pulled from remote location"
411 msgstr ""
479 msgstr ""
412
480
413 #: rhodecode/controllers/admin/repos.py:410
481 #: rhodecode/controllers/admin/repos.py:466
414 msgid "An error occurred during pull from remote location"
482 msgid "An error occurred during pull from remote location"
415 msgstr ""
483 msgstr ""
416
484
417 #: rhodecode/controllers/admin/repos_groups.py:83
485 #: rhodecode/controllers/admin/repos.py:482
486 msgid "Nothing"
487 msgstr ""
488
489 #: rhodecode/controllers/admin/repos.py:484
490 #, python-format
491 msgid "Marked repo %s as fork of %s"
492 msgstr ""
493
494 #: rhodecode/controllers/admin/repos.py:488
495 msgid "An error occurred during this operation"
496 msgstr ""
497
498 #: rhodecode/controllers/admin/repos_groups.py:116
418 #, python-format
499 #, python-format
419 msgid "created repos group %s"
500 msgid "created repos group %s"
420 msgstr ""
501 msgstr ""
421
502
422 #: rhodecode/controllers/admin/repos_groups.py:96
503 #: rhodecode/controllers/admin/repos_groups.py:129
423 #, python-format
504 #, python-format
424 msgid "error occurred during creation of repos group %s"
505 msgid "error occurred during creation of repos group %s"
425 msgstr ""
506 msgstr ""
426
507
427 #: rhodecode/controllers/admin/repos_groups.py:130
508 #: rhodecode/controllers/admin/repos_groups.py:163
428 #, python-format
509 #, python-format
429 msgid "updated repos group %s"
510 msgid "updated repos group %s"
430 msgstr ""
511 msgstr ""
431
512
432 #: rhodecode/controllers/admin/repos_groups.py:143
513 #: rhodecode/controllers/admin/repos_groups.py:176
433 #, python-format
514 #, python-format
434 msgid "error occurred during update of repos group %s"
515 msgid "error occurred during update of repos group %s"
435 msgstr ""
516 msgstr ""
436
517
437 #: rhodecode/controllers/admin/repos_groups.py:164
518 #: rhodecode/controllers/admin/repos_groups.py:194
438 #, python-format
519 #, python-format
439 msgid "This group contains %s repositores and cannot be deleted"
520 msgid "This group contains %s repositores and cannot be deleted"
440 msgstr ""
521 msgstr ""
441
522
442 #: rhodecode/controllers/admin/repos_groups.py:171
523 #: rhodecode/controllers/admin/repos_groups.py:202
443 #, python-format
524 #, python-format
444 msgid "removed repos group %s"
525 msgid "removed repos group %s"
445 msgstr ""
526 msgstr ""
446
527
447 #: rhodecode/controllers/admin/repos_groups.py:175
528 #: rhodecode/controllers/admin/repos_groups.py:208
529 msgid "Cannot delete this group it still contains subgroups"
530 msgstr ""
531
532 #: rhodecode/controllers/admin/repos_groups.py:213
533 #: rhodecode/controllers/admin/repos_groups.py:218
448 #, python-format
534 #, python-format
449 msgid "error occurred during deletion of repos group %s"
535 msgid "error occurred during deletion of repos group %s"
450 msgstr ""
536 msgstr ""
451
537
452 #: rhodecode/controllers/admin/settings.py:109
538 #: rhodecode/controllers/admin/repos_groups.py:238
539 msgid "An error occurred during deletion of group user"
540 msgstr ""
541
542 #: rhodecode/controllers/admin/repos_groups.py:258
543 msgid "An error occurred during deletion of group users groups"
544 msgstr ""
545
546 #: rhodecode/controllers/admin/settings.py:121
453 #, python-format
547 #, python-format
454 msgid "Repositories successfully rescanned added: %s,removed: %s"
548 msgid "Repositories successfully rescanned added: %s,removed: %s"
455 msgstr ""
549 msgstr ""
456
550
457 #: rhodecode/controllers/admin/settings.py:118
551 #: rhodecode/controllers/admin/settings.py:129
458 msgid "Whoosh reindex task scheduled"
552 msgid "Whoosh reindex task scheduled"
459 msgstr ""
553 msgstr ""
460
554
461 #: rhodecode/controllers/admin/settings.py:143
555 #: rhodecode/controllers/admin/settings.py:160
462 msgid "Updated application settings"
556 msgid "Updated application settings"
463 msgstr ""
557 msgstr ""
464
558
465 #: rhodecode/controllers/admin/settings.py:148
559 #: rhodecode/controllers/admin/settings.py:164
466 #: rhodecode/controllers/admin/settings.py:215
560 #: rhodecode/controllers/admin/settings.py:275
467 msgid "error occurred during updating application settings"
561 msgid "error occurred during updating application settings"
468 msgstr ""
562 msgstr ""
469
563
470 #: rhodecode/controllers/admin/settings.py:210
564 #: rhodecode/controllers/admin/settings.py:200
471 msgid "Updated mercurial settings"
565 msgid "Updated visualisation settings"
472 msgstr ""
566 msgstr ""
473
567
474 #: rhodecode/controllers/admin/settings.py:236
568 #: rhodecode/controllers/admin/settings.py:205
569 msgid "error occurred during updating visualisation settings"
570 msgstr ""
571
572 #: rhodecode/controllers/admin/settings.py:271
573 msgid "Updated VCS settings"
574 msgstr ""
575
576 #: rhodecode/controllers/admin/settings.py:285
475 msgid "Added new hook"
577 msgid "Added new hook"
476 msgstr ""
578 msgstr ""
477
579
478 #: rhodecode/controllers/admin/settings.py:247
580 #: rhodecode/controllers/admin/settings.py:297
479 msgid "Updated hooks"
581 msgid "Updated hooks"
480 msgstr ""
582 msgstr ""
481
583
482 #: rhodecode/controllers/admin/settings.py:251
584 #: rhodecode/controllers/admin/settings.py:301
483 msgid "error occurred during hook creation"
585 msgid "error occurred during hook creation"
484 msgstr ""
586 msgstr ""
485
587
486 #: rhodecode/controllers/admin/settings.py:310
588 #: rhodecode/controllers/admin/settings.py:320
589 msgid "Email task created"
590 msgstr ""
591
592 #: rhodecode/controllers/admin/settings.py:375
487 msgid "You can't edit this user since it's crucial for entire application"
593 msgid "You can't edit this user since it's crucial for entire application"
488 msgstr ""
594 msgstr ""
489
595
490 #: rhodecode/controllers/admin/settings.py:339
596 #: rhodecode/controllers/admin/settings.py:406
491 msgid "Your account was updated successfully"
597 msgid "Your account was updated successfully"
492 msgstr ""
598 msgstr ""
493
599
494 #: rhodecode/controllers/admin/settings.py:359
600 #: rhodecode/controllers/admin/settings.py:421
601 #: rhodecode/controllers/admin/users.py:191
602 #, python-format
603 msgid "error occurred during update of user %s"
604 msgstr ""
605
495 #: rhodecode/controllers/admin/users.py:130
606 #: rhodecode/controllers/admin/users.py:130
496 #, python-format
607 #, python-format
497 msgid "error occurred during update of user %s"
498 msgstr ""
499
500 #: rhodecode/controllers/admin/users.py:78
501 #, python-format
502 msgid "created user %s"
608 msgid "created user %s"
503 msgstr ""
609 msgstr ""
504
610
505 #: rhodecode/controllers/admin/users.py:90
611 #: rhodecode/controllers/admin/users.py:142
506 #, python-format
612 #, python-format
507 msgid "error occurred during creation of user %s"
613 msgid "error occurred during creation of user %s"
508 msgstr ""
614 msgstr ""
509
615
510 #: rhodecode/controllers/admin/users.py:116
616 #: rhodecode/controllers/admin/users.py:171
511 msgid "User updated successfully"
617 msgid "User updated successfully"
512 msgstr ""
618 msgstr ""
513
619
514 #: rhodecode/controllers/admin/users.py:146
620 #: rhodecode/controllers/admin/users.py:207
515 msgid "successfully deleted user"
621 msgid "successfully deleted user"
516 msgstr ""
622 msgstr ""
517
623
518 #: rhodecode/controllers/admin/users.py:150
624 #: rhodecode/controllers/admin/users.py:212
519 msgid "An error occurred during deletion of user"
625 msgid "An error occurred during deletion of user"
520 msgstr ""
626 msgstr ""
521
627
522 #: rhodecode/controllers/admin/users.py:166
628 #: rhodecode/controllers/admin/users.py:226
523 msgid "You can't edit this user"
629 msgid "You can't edit this user"
524 msgstr ""
630 msgstr ""
525
631
526 #: rhodecode/controllers/admin/users.py:195
632 #: rhodecode/controllers/admin/users.py:266
527 #: rhodecode/controllers/admin/users_groups.py:202
528 msgid "Granted 'repository create' permission to user"
633 msgid "Granted 'repository create' permission to user"
529 msgstr ""
634 msgstr ""
530
635
531 #: rhodecode/controllers/admin/users.py:204
636 #: rhodecode/controllers/admin/users.py:271
532 #: rhodecode/controllers/admin/users_groups.py:211
533 msgid "Revoked 'repository create' permission to user"
637 msgid "Revoked 'repository create' permission to user"
534 msgstr ""
638 msgstr ""
535
639
536 #: rhodecode/controllers/admin/users_groups.py:74
640 #: rhodecode/controllers/admin/users.py:277
641 msgid "Granted 'repository fork' permission to user"
642 msgstr ""
643
644 #: rhodecode/controllers/admin/users.py:282
645 msgid "Revoked 'repository fork' permission to user"
646 msgstr ""
647
648 #: rhodecode/controllers/admin/users.py:288
649 #: rhodecode/controllers/admin/users_groups.py:255
650 msgid "An error occurred during permissions saving"
651 msgstr ""
652
653 #: rhodecode/controllers/admin/users.py:303
654 #, python-format
655 msgid "Added email %s to user"
656 msgstr ""
657
658 #: rhodecode/controllers/admin/users.py:309
659 msgid "An error occurred during email saving"
660 msgstr ""
661
662 #: rhodecode/controllers/admin/users.py:319
663 msgid "Removed email from user"
664 msgstr ""
665
666 #: rhodecode/controllers/admin/users_groups.py:84
537 #, python-format
667 #, python-format
538 msgid "created users group %s"
668 msgid "created users group %s"
539 msgstr ""
669 msgstr ""
540
670
541 #: rhodecode/controllers/admin/users_groups.py:86
671 #: rhodecode/controllers/admin/users_groups.py:95
542 #, python-format
672 #, python-format
543 msgid "error occurred during creation of users group %s"
673 msgid "error occurred during creation of users group %s"
544 msgstr ""
674 msgstr ""
545
675
546 #: rhodecode/controllers/admin/users_groups.py:119
676 #: rhodecode/controllers/admin/users_groups.py:135
547 #, python-format
677 #, python-format
548 msgid "updated users group %s"
678 msgid "updated users group %s"
549 msgstr ""
679 msgstr ""
550
680
551 #: rhodecode/controllers/admin/users_groups.py:138
681 #: rhodecode/controllers/admin/users_groups.py:157
552 #, python-format
682 #, python-format
553 msgid "error occurred during update of users group %s"
683 msgid "error occurred during update of users group %s"
554 msgstr ""
684 msgstr ""
555
685
556 #: rhodecode/controllers/admin/users_groups.py:154
686 #: rhodecode/controllers/admin/users_groups.py:174
557 msgid "successfully deleted users group"
687 msgid "successfully deleted users group"
558 msgstr ""
688 msgstr ""
559
689
560 #: rhodecode/controllers/admin/users_groups.py:158
690 #: rhodecode/controllers/admin/users_groups.py:179
561 msgid "An error occurred during deletion of users group"
691 msgid "An error occurred during deletion of users group"
562 msgstr ""
692 msgstr ""
563
693
564 #: rhodecode/lib/__init__.py:279
694 #: rhodecode/controllers/admin/users_groups.py:233
565 msgid "year"
695 msgid "Granted 'repository create' permission to users group"
566 msgstr ""
696 msgstr ""
567
697
568 #: rhodecode/lib/__init__.py:280
698 #: rhodecode/controllers/admin/users_groups.py:238
569 msgid "month"
699 msgid "Revoked 'repository create' permission to users group"
570 msgstr ""
700 msgstr ""
571
701
572 #: rhodecode/lib/__init__.py:281
702 #: rhodecode/controllers/admin/users_groups.py:244
573 msgid "day"
703 msgid "Granted 'repository fork' permission to users group"
574 msgstr ""
704 msgstr ""
575
705
576 #: rhodecode/lib/__init__.py:282
706 #: rhodecode/controllers/admin/users_groups.py:249
577 msgid "hour"
707 msgid "Revoked 'repository fork' permission to users group"
578 msgstr ""
708 msgstr ""
579
709
580 #: rhodecode/lib/__init__.py:283
710 #: rhodecode/lib/auth.py:499
581 msgid "minute"
582 msgstr ""
583
584 #: rhodecode/lib/__init__.py:284
585 msgid "second"
586 msgstr ""
587
588 #: rhodecode/lib/__init__.py:293
589 msgid "ago"
590 msgstr ""
591
592 #: rhodecode/lib/__init__.py:296
593 msgid "just now"
594 msgstr ""
595
596 #: rhodecode/lib/auth.py:377
597 msgid "You need to be a registered user to perform this action"
711 msgid "You need to be a registered user to perform this action"
598 msgstr ""
712 msgstr ""
599
713
600 #: rhodecode/lib/auth.py:421
714 #: rhodecode/lib/auth.py:540
601 msgid "You need to be a signed in to view this page"
715 msgid "You need to be a signed in to view this page"
602 msgstr ""
716 msgstr ""
603
717
604 #: rhodecode/lib/helpers.py:307
718 #: rhodecode/lib/diffs.py:86
719 msgid "Changeset was too big and was cut off, use diff menu to display this diff"
720 msgstr ""
721
722 #: rhodecode/lib/diffs.py:96
723 msgid "No changes detected"
724 msgstr ""
725
726 #: rhodecode/lib/helpers.py:372
727 #, python-format
728 msgid "%a, %d %b %Y %H:%M:%S"
729 msgstr ""
730
731 #: rhodecode/lib/helpers.py:484
605 msgid "True"
732 msgid "True"
606 msgstr ""
733 msgstr ""
607
734
608 #: rhodecode/lib/helpers.py:311
735 #: rhodecode/lib/helpers.py:488
609 msgid "False"
736 msgid "False"
610 msgstr ""
737 msgstr ""
611
738
612 #: rhodecode/lib/helpers.py:352
739 #: rhodecode/lib/helpers.py:532
740 msgid "Changeset not found"
741 msgstr ""
742
743 #: rhodecode/lib/helpers.py:555
613 #, python-format
744 #, python-format
614 msgid "Show all combined changesets %s->%s"
745 msgid "Show all combined changesets %s->%s"
615 msgstr ""
746 msgstr ""
616
747
617 #: rhodecode/lib/helpers.py:356
748 #: rhodecode/lib/helpers.py:561
618 msgid "compare view"
749 msgid "compare view"
619 msgstr ""
750 msgstr ""
620
751
621 #: rhodecode/lib/helpers.py:365
622 msgid "and"
623 msgstr ""
624
625 #: rhodecode/lib/helpers.py:365
626 #, python-format
627 msgid "%s more"
628 msgstr ""
629
630 #: rhodecode/lib/helpers.py:367 rhodecode/templates/changelog/changelog.html:14
631 #: rhodecode/templates/changelog/changelog.html:39
632 msgid "revisions"
633 msgstr ""
634
635 #: rhodecode/lib/helpers.py:385
636 msgid "fork name "
637 msgstr ""
638
639 #: rhodecode/lib/helpers.py:388
640 msgid "[deleted] repository"
641 msgstr ""
642
643 #: rhodecode/lib/helpers.py:389 rhodecode/lib/helpers.py:393
644 msgid "[created] repository"
645 msgstr ""
646
647 #: rhodecode/lib/helpers.py:390 rhodecode/lib/helpers.py:394
648 msgid "[forked] repository"
649 msgstr ""
650
651 #: rhodecode/lib/helpers.py:391 rhodecode/lib/helpers.py:395
652 msgid "[updated] repository"
653 msgstr ""
654
655 #: rhodecode/lib/helpers.py:392
656 msgid "[delete] repository"
657 msgstr ""
658
659 #: rhodecode/lib/helpers.py:396
660 msgid "[pushed] into"
661 msgstr ""
662
663 #: rhodecode/lib/helpers.py:397
664 msgid "[committed via RhodeCode] into"
665 msgstr ""
666
667 #: rhodecode/lib/helpers.py:398
668 msgid "[pulled from remote] into"
669 msgstr ""
670
671 #: rhodecode/lib/helpers.py:399
672 msgid "[pulled] from"
673 msgstr ""
674
675 #: rhodecode/lib/helpers.py:400
676 msgid "[started following] repository"
677 msgstr ""
678
679 #: rhodecode/lib/helpers.py:401
680 msgid "[stopped following] repository"
681 msgstr ""
682
683 #: rhodecode/lib/helpers.py:577
684 #, python-format
685 msgid " and %s more"
686 msgstr ""
687
688 #: rhodecode/lib/helpers.py:581
752 #: rhodecode/lib/helpers.py:581
753 msgid "and"
754 msgstr ""
755
756 #: rhodecode/lib/helpers.py:582
757 #, python-format
758 msgid "%s more"
759 msgstr ""
760
761 #: rhodecode/lib/helpers.py:583 rhodecode/templates/changelog/changelog.html:48
762 msgid "revisions"
763 msgstr ""
764
765 #: rhodecode/lib/helpers.py:606
766 msgid "fork name "
767 msgstr ""
768
769 #: rhodecode/lib/helpers.py:620
770 #: rhodecode/templates/pullrequests/pullrequest_show.html:4
771 #: rhodecode/templates/pullrequests/pullrequest_show.html:12
772 #, python-format
773 msgid "Pull request #%s"
774 msgstr ""
775
776 #: rhodecode/lib/helpers.py:626
777 msgid "[deleted] repository"
778 msgstr ""
779
780 #: rhodecode/lib/helpers.py:628 rhodecode/lib/helpers.py:638
781 msgid "[created] repository"
782 msgstr ""
783
784 #: rhodecode/lib/helpers.py:630
785 msgid "[created] repository as fork"
786 msgstr ""
787
788 #: rhodecode/lib/helpers.py:632 rhodecode/lib/helpers.py:640
789 msgid "[forked] repository"
790 msgstr ""
791
792 #: rhodecode/lib/helpers.py:634 rhodecode/lib/helpers.py:642
793 msgid "[updated] repository"
794 msgstr ""
795
796 #: rhodecode/lib/helpers.py:636
797 msgid "[delete] repository"
798 msgstr ""
799
800 #: rhodecode/lib/helpers.py:644
801 msgid "[created] user"
802 msgstr ""
803
804 #: rhodecode/lib/helpers.py:646
805 msgid "[updated] user"
806 msgstr ""
807
808 #: rhodecode/lib/helpers.py:648
809 msgid "[created] users group"
810 msgstr ""
811
812 #: rhodecode/lib/helpers.py:650
813 msgid "[updated] users group"
814 msgstr ""
815
816 #: rhodecode/lib/helpers.py:652
817 msgid "[commented] on revision in repository"
818 msgstr ""
819
820 #: rhodecode/lib/helpers.py:654
821 msgid "[commented] on pull request for"
822 msgstr ""
823
824 #: rhodecode/lib/helpers.py:656
825 msgid "[closed] pull request for"
826 msgstr ""
827
828 #: rhodecode/lib/helpers.py:658
829 msgid "[pushed] into"
830 msgstr ""
831
832 #: rhodecode/lib/helpers.py:660
833 msgid "[committed via RhodeCode] into repository"
834 msgstr ""
835
836 #: rhodecode/lib/helpers.py:662
837 msgid "[pulled from remote] into repository"
838 msgstr ""
839
840 #: rhodecode/lib/helpers.py:664
841 msgid "[pulled] from"
842 msgstr ""
843
844 #: rhodecode/lib/helpers.py:666
845 msgid "[started following] repository"
846 msgstr ""
847
848 #: rhodecode/lib/helpers.py:668
849 msgid "[stopped following] repository"
850 msgstr ""
851
852 #: rhodecode/lib/helpers.py:840
853 #, python-format
854 msgid " and %s more"
855 msgstr ""
856
857 #: rhodecode/lib/helpers.py:844
689 msgid "No Files"
858 msgid "No Files"
690 msgstr ""
859 msgstr ""
691
860
692 #: rhodecode/model/forms.py:66
861 #: rhodecode/lib/utils2.py:335
693 msgid "Invalid username"
862 #, python-format
694 msgstr ""
863 msgid "%d year"
695
864 msgid_plural "%d years"
696 #: rhodecode/model/forms.py:75
865 msgstr[0] ""
697 msgid "This username already exists"
866 msgstr[1] ""
698 msgstr ""
867
699
868 #: rhodecode/lib/utils2.py:336
700 #: rhodecode/model/forms.py:79
869 #, python-format
870 msgid "%d month"
871 msgid_plural "%d months"
872 msgstr[0] ""
873 msgstr[1] ""
874
875 #: rhodecode/lib/utils2.py:337
876 #, python-format
877 msgid "%d day"
878 msgid_plural "%d days"
879 msgstr[0] ""
880 msgstr[1] ""
881
882 #: rhodecode/lib/utils2.py:338
883 #, python-format
884 msgid "%d hour"
885 msgid_plural "%d hours"
886 msgstr[0] ""
887 msgstr[1] ""
888
889 #: rhodecode/lib/utils2.py:339
890 #, python-format
891 msgid "%d minute"
892 msgid_plural "%d minutes"
893 msgstr[0] ""
894 msgstr[1] ""
895
896 #: rhodecode/lib/utils2.py:340
897 #, python-format
898 msgid "%d second"
899 msgid_plural "%d seconds"
900 msgstr[0] ""
901 msgstr[1] ""
902
903 #: rhodecode/lib/utils2.py:355
904 #, python-format
905 msgid "%s ago"
906 msgstr ""
907
908 #: rhodecode/lib/utils2.py:357
909 #, python-format
910 msgid "%s and %s ago"
911 msgstr ""
912
913 #: rhodecode/lib/utils2.py:360
914 msgid "just now"
915 msgstr ""
916
917 #: rhodecode/lib/celerylib/tasks.py:269
918 msgid "password reset link"
919 msgstr ""
920
921 #: rhodecode/model/comment.py:110
922 #, python-format
923 msgid "on line %s"
924 msgstr ""
925
926 #: rhodecode/model/comment.py:157
927 msgid "[Mention]"
928 msgstr ""
929
930 #: rhodecode/model/db.py:1140
931 msgid "Repository no access"
932 msgstr ""
933
934 #: rhodecode/model/db.py:1141
935 msgid "Repository read access"
936 msgstr ""
937
938 #: rhodecode/model/db.py:1142
939 msgid "Repository write access"
940 msgstr ""
941
942 #: rhodecode/model/db.py:1143
943 msgid "Repository admin access"
944 msgstr ""
945
946 #: rhodecode/model/db.py:1145
947 msgid "Repositories Group no access"
948 msgstr ""
949
950 #: rhodecode/model/db.py:1146
951 msgid "Repositories Group read access"
952 msgstr ""
953
954 #: rhodecode/model/db.py:1147
955 msgid "Repositories Group write access"
956 msgstr ""
957
958 #: rhodecode/model/db.py:1148
959 msgid "Repositories Group admin access"
960 msgstr ""
961
962 #: rhodecode/model/db.py:1150
963 msgid "RhodeCode Administrator"
964 msgstr ""
965
966 #: rhodecode/model/db.py:1151
967 msgid "Repository creation disabled"
968 msgstr ""
969
970 #: rhodecode/model/db.py:1152
971 msgid "Repository creation enabled"
972 msgstr ""
973
974 #: rhodecode/model/db.py:1153
975 msgid "Repository forking disabled"
976 msgstr ""
977
978 #: rhodecode/model/db.py:1154
979 msgid "Repository forking enabled"
980 msgstr ""
981
982 #: rhodecode/model/db.py:1155
983 msgid "Register disabled"
984 msgstr ""
985
986 #: rhodecode/model/db.py:1156
987 msgid "Register new user with RhodeCode with manual activation"
988 msgstr ""
989
990 #: rhodecode/model/db.py:1159
991 msgid "Register new user with RhodeCode with auto activation"
992 msgstr ""
993
994 #: rhodecode/model/db.py:1579
995 msgid "Not Reviewed"
996 msgstr ""
997
998 #: rhodecode/model/db.py:1580
999 msgid "Approved"
1000 msgstr ""
1001
1002 #: rhodecode/model/db.py:1581
1003 msgid "Rejected"
1004 msgstr ""
1005
1006 #: rhodecode/model/db.py:1582
1007 msgid "Under Review"
1008 msgstr ""
1009
1010 #: rhodecode/model/forms.py:43
1011 msgid "Please enter a login"
1012 msgstr ""
1013
1014 #: rhodecode/model/forms.py:44
1015 #, python-format
1016 msgid "Enter a value %(min)i characters long or more"
1017 msgstr ""
1018
1019 #: rhodecode/model/forms.py:52
1020 msgid "Please enter a password"
1021 msgstr ""
1022
1023 #: rhodecode/model/forms.py:53
1024 #, python-format
1025 msgid "Enter %(min)i characters or more"
1026 msgstr ""
1027
1028 #: rhodecode/model/notification.py:220
1029 msgid "commented on commit"
1030 msgstr ""
1031
1032 #: rhodecode/model/notification.py:221
1033 msgid "sent message"
1034 msgstr ""
1035
1036 #: rhodecode/model/notification.py:222
1037 msgid "mentioned you"
1038 msgstr ""
1039
1040 #: rhodecode/model/notification.py:223
1041 msgid "registered in RhodeCode"
1042 msgstr ""
1043
1044 #: rhodecode/model/notification.py:224
1045 msgid "opened new pull request"
1046 msgstr ""
1047
1048 #: rhodecode/model/notification.py:225
1049 msgid "commented on pull request"
1050 msgstr ""
1051
1052 #: rhodecode/model/pull_request.py:84
1053 #, python-format
1054 msgid "%(user)s wants you to review pull request #%(pr_id)s"
1055 msgstr ""
1056
1057 #: rhodecode/model/scm.py:535
1058 msgid "latest tip"
1059 msgstr ""
1060
1061 #: rhodecode/model/user.py:230
1062 msgid "new user registration"
1063 msgstr ""
1064
1065 #: rhodecode/model/user.py:255 rhodecode/model/user.py:277
1066 #: rhodecode/model/user.py:299
1067 msgid "You can't Edit this user since it's crucial for entire application"
1068 msgstr ""
1069
1070 #: rhodecode/model/user.py:323
1071 msgid "You can't remove this user since it's crucial for entire application"
1072 msgstr ""
1073
1074 #: rhodecode/model/user.py:329
1075 #, python-format
1076 msgid ""
1077 "user \"%s\" still owns %s repositories and cannot be removed. Switch "
1078 "owners or remove those repositories. %s"
1079 msgstr ""
1080
1081 #: rhodecode/model/validators.py:35 rhodecode/model/validators.py:36
1082 msgid "Value cannot be an empty list"
1083 msgstr ""
1084
1085 #: rhodecode/model/validators.py:82
1086 #, python-format
1087 msgid "Username \"%(username)s\" already exists"
1088 msgstr ""
1089
1090 #: rhodecode/model/validators.py:84
1091 #, python-format
1092 msgid "Username \"%(username)s\" is forbidden"
1093 msgstr ""
1094
1095 #: rhodecode/model/validators.py:86
701 msgid ""
1096 msgid ""
702 "Username may only contain alphanumeric characters underscores, periods or"
1097 "Username may only contain alphanumeric characters underscores, periods or"
703 " dashes and must begin with alphanumeric character"
1098 " dashes and must begin with alphanumeric character"
704 msgstr ""
1099 msgstr ""
705
1100
706 #: rhodecode/model/forms.py:94
1101 #: rhodecode/model/validators.py:114
707 msgid "Invalid group name"
1102 #, python-format
708 msgstr ""
1103 msgid "Username %(username)s is not valid"
709
1104 msgstr ""
710 #: rhodecode/model/forms.py:104
1105
711 msgid "This users group already exists"
1106 #: rhodecode/model/validators.py:133
712 msgstr ""
1107 msgid "Invalid users group name"
713
1108 msgstr ""
714 #: rhodecode/model/forms.py:110
1109
1110 #: rhodecode/model/validators.py:134
1111 #, python-format
1112 msgid "Users group \"%(usersgroup)s\" already exists"
1113 msgstr ""
1114
1115 #: rhodecode/model/validators.py:136
715 msgid ""
1116 msgid ""
716 "Group name may only contain alphanumeric characters underscores, periods "
1117 "users group name may only contain alphanumeric characters underscores, "
717 "or dashes and must begin with alphanumeric character"
1118 "periods or dashes and must begin with alphanumeric character"
718 msgstr ""
1119 msgstr ""
719
1120
720 #: rhodecode/model/forms.py:132
1121 #: rhodecode/model/validators.py:174
721 msgid "Cannot assign this group as parent"
1122 msgid "Cannot assign this group as parent"
722 msgstr ""
1123 msgstr ""
723
1124
724 #: rhodecode/model/forms.py:148
1125 #: rhodecode/model/validators.py:175
725 msgid "This group already exists"
1126 #, python-format
726 msgstr ""
1127 msgid "Group \"%(group_name)s\" already exists"
727
1128 msgstr ""
728 #: rhodecode/model/forms.py:164 rhodecode/model/forms.py:172
1129
729 #: rhodecode/model/forms.py:180
1130 #: rhodecode/model/validators.py:177
730 msgid "Invalid characters in password"
1131 #, python-format
731 msgstr ""
1132 msgid "Repository with name \"%(group_name)s\" already exists"
732
1133 msgstr ""
733 #: rhodecode/model/forms.py:191
1134
1135 #: rhodecode/model/validators.py:235
1136 msgid "Invalid characters (non-ascii) in password"
1137 msgstr ""
1138
1139 #: rhodecode/model/validators.py:250
734 msgid "Passwords do not match"
1140 msgid "Passwords do not match"
735 msgstr ""
1141 msgstr ""
736
1142
737 #: rhodecode/model/forms.py:196
1143 #: rhodecode/model/validators.py:267
738 msgid "invalid password"
1144 msgid "invalid password"
739 msgstr ""
1145 msgstr ""
740
1146
741 #: rhodecode/model/forms.py:197
1147 #: rhodecode/model/validators.py:268
742 msgid "invalid user name"
1148 msgid "invalid user name"
743 msgstr ""
1149 msgstr ""
744
1150
745 #: rhodecode/model/forms.py:198
1151 #: rhodecode/model/validators.py:269
746 msgid "Your account is disabled"
1152 msgid "Your account is disabled"
747 msgstr ""
1153 msgstr ""
748
1154
749 #: rhodecode/model/forms.py:233
1155 #: rhodecode/model/validators.py:313
750 msgid "This username is not valid"
1156 #, python-format
751 msgstr ""
1157 msgid "Repository name %(repo)s is disallowed"
752
1158 msgstr ""
753 #: rhodecode/model/forms.py:245
1159
754 msgid "This repository name is disallowed"
1160 #: rhodecode/model/validators.py:315
755 msgstr ""
756
757 #: rhodecode/model/forms.py:266
758 #, python-format
1161 #, python-format
759 msgid "This repository already exists in group \"%s\""
1162 msgid "Repository named %(repo)s already exists"
760 msgstr ""
1163 msgstr ""
761
1164
762 #: rhodecode/model/forms.py:274
1165 #: rhodecode/model/validators.py:316
763 msgid "This repository already exists"
1166 #, python-format
764 msgstr ""
1167 msgid "Repository \"%(repo)s\" already exists in group \"%(group)s\""
765
1168 msgstr ""
766 #: rhodecode/model/forms.py:312 rhodecode/model/forms.py:319
1169
1170 #: rhodecode/model/validators.py:318
1171 #, python-format
1172 msgid "Repositories group with name \"%(repo)s\" already exists"
1173 msgstr ""
1174
1175 #: rhodecode/model/validators.py:431
767 msgid "invalid clone url"
1176 msgid "invalid clone url"
768 msgstr ""
1177 msgstr ""
769
1178
770 #: rhodecode/model/forms.py:322
1179 #: rhodecode/model/validators.py:432
771 msgid "Invalid clone url, provide a valid clone http\\s url"
1180 msgid "Invalid clone url, provide a valid clone http(s)/svn+http(s) url"
772 msgstr ""
1181 msgstr ""
773
1182
774 #: rhodecode/model/forms.py:334
1183 #: rhodecode/model/validators.py:457
775 msgid "Fork have to be the same type as original"
1184 msgid "Fork have to be the same type as parent"
776 msgstr ""
1185 msgstr ""
777
1186
778 #: rhodecode/model/forms.py:341
1187 #: rhodecode/model/validators.py:478
779 msgid "This username or users group name is not valid"
1188 msgid "This username or users group name is not valid"
780 msgstr ""
1189 msgstr ""
781
1190
782 #: rhodecode/model/forms.py:403
1191 #: rhodecode/model/validators.py:562
783 msgid "This is not a valid path"
1192 msgid "This is not a valid path"
784 msgstr ""
1193 msgstr ""
785
1194
786 #: rhodecode/model/forms.py:416
1195 #: rhodecode/model/validators.py:577
787 msgid "This e-mail address is already taken"
1196 msgid "This e-mail address is already taken"
788 msgstr ""
1197 msgstr ""
789
1198
790 #: rhodecode/model/forms.py:427
1199 #: rhodecode/model/validators.py:597
791 msgid "This e-mail address doesn't exist."
1200 #, python-format
792 msgstr ""
1201 msgid "e-mail \"%(email)s\" does not exist."
793
1202 msgstr ""
794 #: rhodecode/model/forms.py:447
1203
1204 #: rhodecode/model/validators.py:634
795 msgid ""
1205 msgid ""
796 "The LDAP Login attribute of the CN must be specified - this is the name "
1206 "The LDAP Login attribute of the CN must be specified - this is the name "
797 "of the attribute that is equivalent to 'username'"
1207 "of the attribute that is equivalent to \"username\""
798 msgstr ""
1208 msgstr ""
799
1209
800 #: rhodecode/model/forms.py:466
1210 #: rhodecode/model/validators.py:653
801 msgid "Please enter a login"
802 msgstr ""
803
804 #: rhodecode/model/forms.py:467
805 #, python-format
806 msgid "Enter a value %(min)i characters long or more"
807 msgstr ""
808
809 #: rhodecode/model/forms.py:475
810 msgid "Please enter a password"
811 msgstr ""
812
813 #: rhodecode/model/forms.py:476
814 #, python-format
1211 #, python-format
815 msgid "Enter %(min)i characters or more"
1212 msgid "Revisions %(revs)s are already part of pull request or have set status"
816 msgstr ""
1213 msgstr ""
817
1214
818 #: rhodecode/model/user.py:145
1215 #: rhodecode/templates/index.html:3
819 msgid "[RhodeCode] New User registration"
820 msgstr ""
821
822 #: rhodecode/model/user.py:157 rhodecode/model/user.py:179
823 msgid "You can't Edit this user since it's crucial for entire application"
824 msgstr ""
825
826 #: rhodecode/model/user.py:201
827 msgid "You can't remove this user since it's crucial for entire application"
828 msgstr ""
829
830 #: rhodecode/model/user.py:204
831 #, python-format
832 msgid ""
833 "This user still owns %s repositories and cannot be removed. Switch owners"
834 " or remove those repositories"
835 msgstr ""
836
837 #: rhodecode/templates/index.html:4
838 msgid "Dashboard"
1216 msgid "Dashboard"
839 msgstr ""
1217 msgstr ""
840
1218
841 #: rhodecode/templates/index_base.html:22
1219 #: rhodecode/templates/index_base.html:6
842 #: rhodecode/templates/admin/users/user_edit_my_account.html:102
1220 #: rhodecode/templates/repo_switcher_list.html:4
1221 #: rhodecode/templates/admin/repos/repos.html:9
1222 #: rhodecode/templates/admin/users/user_edit_my_account.html:31
1223 #: rhodecode/templates/admin/users/users.html:9
1224 #: rhodecode/templates/bookmarks/bookmarks.html:10
1225 #: rhodecode/templates/branches/branches.html:9
1226 #: rhodecode/templates/journal/journal.html:40
1227 #: rhodecode/templates/tags/tags.html:10
843 msgid "quick filter..."
1228 msgid "quick filter..."
844 msgstr ""
1229 msgstr ""
845
1230
846 #: rhodecode/templates/index_base.html:23
1231 #: rhodecode/templates/index_base.html:6
847 #: rhodecode/templates/base/base.html:300
1232 #: rhodecode/templates/admin/repos/repos.html:9
1233 #: rhodecode/templates/base/base.html:221
848 msgid "repositories"
1234 msgid "repositories"
849 msgstr ""
1235 msgstr ""
850
1236
1237 #: rhodecode/templates/index_base.html:13
1238 #: rhodecode/templates/index_base.html:15
1239 #: rhodecode/templates/admin/repos/repos.html:21
1240 msgid "ADD REPOSITORY"
1241 msgstr ""
1242
851 #: rhodecode/templates/index_base.html:29
1243 #: rhodecode/templates/index_base.html:29
852 #: rhodecode/templates/admin/repos/repos.html:22
853 msgid "ADD NEW REPOSITORY"
854 msgstr ""
855
856 #: rhodecode/templates/index_base.html:41
857 #: rhodecode/templates/admin/repos_groups/repos_groups_add.html:32
1244 #: rhodecode/templates/admin/repos_groups/repos_groups_add.html:32
858 #: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:32
1245 #: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:32
859 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:33
1246 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:33
@@ -862,158 +1249,158 b' msgstr ""'
862 msgid "Group name"
1249 msgid "Group name"
863 msgstr ""
1250 msgstr ""
864
1251
865 #: rhodecode/templates/index_base.html:42
1252 #: rhodecode/templates/index_base.html:30
866 #: rhodecode/templates/index_base.html:73
1253 #: rhodecode/templates/index_base.html:71
867 #: rhodecode/templates/admin/repos/repo_add_base.html:44
1254 #: rhodecode/templates/index_base.html:142
868 #: rhodecode/templates/admin/repos/repo_edit.html:64
1255 #: rhodecode/templates/index_base.html:168
869 #: rhodecode/templates/admin/repos/repos.html:31
1256 #: rhodecode/templates/admin/repos/repo_add_base.html:56
1257 #: rhodecode/templates/admin/repos/repo_edit.html:75
1258 #: rhodecode/templates/admin/repos/repos.html:72
870 #: rhodecode/templates/admin/repos_groups/repos_groups_add.html:41
1259 #: rhodecode/templates/admin/repos_groups/repos_groups_add.html:41
871 #: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:41
1260 #: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:41
872 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:34
1261 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:34
873 #: rhodecode/templates/settings/repo_fork.html:40
1262 #: rhodecode/templates/forks/fork.html:59
874 #: rhodecode/templates/settings/repo_settings.html:40
1263 #: rhodecode/templates/settings/repo_settings.html:66
875 #: rhodecode/templates/summary/summary.html:92
1264 #: rhodecode/templates/summary/summary.html:105
876 msgid "Description"
1265 msgid "Description"
877 msgstr ""
1266 msgstr ""
878
1267
879 #: rhodecode/templates/index_base.html:53
1268 #: rhodecode/templates/index_base.html:40
880 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46
1269 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:46
881 msgid "Repositories group"
1270 msgid "Repositories group"
882 msgstr ""
1271 msgstr ""
883
1272
1273 #: rhodecode/templates/index_base.html:70
1274 #: rhodecode/templates/index_base.html:166
1275 #: rhodecode/templates/admin/repos/repo_add_base.html:9
1276 #: rhodecode/templates/admin/repos/repo_edit.html:32
1277 #: rhodecode/templates/admin/repos/repos.html:70
1278 #: rhodecode/templates/admin/users/user_edit.html:192
1279 #: rhodecode/templates/admin/users/user_edit_my_account.html:59
1280 #: rhodecode/templates/admin/users/user_edit_my_account.html:157
1281 #: rhodecode/templates/admin/users/user_edit_my_account.html:193
1282 #: rhodecode/templates/admin/users/user_edit_my_account_repos.html:6
1283 #: rhodecode/templates/bookmarks/bookmarks.html:36
1284 #: rhodecode/templates/bookmarks/bookmarks_data.html:6
1285 #: rhodecode/templates/branches/branches.html:51
1286 #: rhodecode/templates/files/files_browser.html:47
1287 #: rhodecode/templates/journal/journal.html:59
1288 #: rhodecode/templates/journal/journal.html:107
1289 #: rhodecode/templates/journal/journal.html:186
1290 #: rhodecode/templates/settings/repo_settings.html:31
1291 #: rhodecode/templates/summary/summary.html:43
1292 #: rhodecode/templates/summary/summary.html:123
1293 #: rhodecode/templates/tags/tags.html:36
1294 #: rhodecode/templates/tags/tags_data.html:6
1295 msgid "Name"
1296 msgstr ""
1297
884 #: rhodecode/templates/index_base.html:72
1298 #: rhodecode/templates/index_base.html:72
885 #: rhodecode/templates/admin/repos/repo_add_base.html:9
1299 msgid "Last change"
886 #: rhodecode/templates/admin/repos/repo_edit.html:32
1300 msgstr ""
887 #: rhodecode/templates/admin/repos/repos.html:30
1301
888 #: rhodecode/templates/admin/users/user_edit_my_account.html:117
1302 #: rhodecode/templates/index_base.html:73
889 #: rhodecode/templates/files/files_browser.html:157
1303 #: rhodecode/templates/index_base.html:171
890 #: rhodecode/templates/settings/repo_settings.html:31
1304 #: rhodecode/templates/admin/users/user_edit_my_account.html:159
891 #: rhodecode/templates/summary/summary.html:31
1305 #: rhodecode/templates/journal/journal.html:188
892 #: rhodecode/templates/summary/summary.html:107
1306 msgid "Tip"
893 msgid "Name"
894 msgstr ""
1307 msgstr ""
895
1308
896 #: rhodecode/templates/index_base.html:74
1309 #: rhodecode/templates/index_base.html:74
897 #: rhodecode/templates/admin/repos/repos.html:32
1310 #: rhodecode/templates/index_base.html:173
898 #: rhodecode/templates/summary/summary.html:114
1311 #: rhodecode/templates/admin/repos/repo_edit.html:121
899 msgid "Last change"
1312 #: rhodecode/templates/admin/repos/repos.html:73
1313 msgid "Owner"
900 msgstr ""
1314 msgstr ""
901
1315
902 #: rhodecode/templates/index_base.html:75
1316 #: rhodecode/templates/index_base.html:75
903 #: rhodecode/templates/admin/repos/repos.html:33
1317 #: rhodecode/templates/summary/summary.html:48
904 msgid "Tip"
1318 #: rhodecode/templates/summary/summary.html:51
1319 msgid "RSS"
905 msgstr ""
1320 msgstr ""
906
1321
907 #: rhodecode/templates/index_base.html:76
1322 #: rhodecode/templates/index_base.html:76
908 #: rhodecode/templates/admin/repos/repo_edit.html:97
909 msgid "Owner"
910 msgstr ""
911
912 #: rhodecode/templates/index_base.html:77
913 #: rhodecode/templates/journal/public_journal.html:20
914 #: rhodecode/templates/summary/summary.html:180
915 #: rhodecode/templates/summary/summary.html:183
916 msgid "RSS"
917 msgstr ""
918
919 #: rhodecode/templates/index_base.html:78
920 #: rhodecode/templates/journal/public_journal.html:23
921 #: rhodecode/templates/summary/summary.html:181
922 #: rhodecode/templates/summary/summary.html:184
923 msgid "Atom"
1323 msgid "Atom"
924 msgstr ""
1324 msgstr ""
925
1325
926 #: rhodecode/templates/index_base.html:87
1326 #: rhodecode/templates/index_base.html:110
927 #: rhodecode/templates/index_base.html:89
1327 #: rhodecode/templates/index_base.html:112
928 #: rhodecode/templates/index_base.html:91
929 #: rhodecode/templates/base/base.html:209
930 #: rhodecode/templates/base/base.html:211
931 #: rhodecode/templates/base/base.html:213
932 #: rhodecode/templates/summary/summary.html:4
933 msgid "Summary"
934 msgstr ""
935
936 #: rhodecode/templates/index_base.html:95
937 #: rhodecode/templates/index_base.html:97
938 #: rhodecode/templates/index_base.html:99
939 #: rhodecode/templates/base/base.html:225
940 #: rhodecode/templates/base/base.html:227
941 #: rhodecode/templates/base/base.html:229
942 #: rhodecode/templates/changelog/changelog.html:6
943 #: rhodecode/templates/changelog/changelog.html:14
944 msgid "Changelog"
945 msgstr ""
946
947 #: rhodecode/templates/index_base.html:103
948 #: rhodecode/templates/index_base.html:105
949 #: rhodecode/templates/index_base.html:107
950 #: rhodecode/templates/base/base.html:268
951 #: rhodecode/templates/base/base.html:270
952 #: rhodecode/templates/base/base.html:272
953 #: rhodecode/templates/files/files.html:4
954 msgid "Files"
955 msgstr ""
956
957 #: rhodecode/templates/index_base.html:116
958 #: rhodecode/templates/admin/repos/repos.html:42
959 #: rhodecode/templates/admin/users/user_edit_my_account.html:127
960 #: rhodecode/templates/summary/summary.html:48
961 msgid "Mercurial repository"
962 msgstr ""
963
964 #: rhodecode/templates/index_base.html:118
965 #: rhodecode/templates/admin/repos/repos.html:44
966 #: rhodecode/templates/admin/users/user_edit_my_account.html:129
967 #: rhodecode/templates/summary/summary.html:51
968 msgid "Git repository"
969 msgstr ""
970
971 #: rhodecode/templates/index_base.html:123
972 #: rhodecode/templates/admin/repos/repo_edit_perms.html:16
973 #: rhodecode/templates/journal/journal.html:53
974 #: rhodecode/templates/summary/summary.html:56
975 msgid "private repository"
976 msgstr ""
977
978 #: rhodecode/templates/index_base.html:125
979 #: rhodecode/templates/journal/journal.html:55
980 #: rhodecode/templates/summary/summary.html:58
981 msgid "public repository"
982 msgstr ""
983
984 #: rhodecode/templates/index_base.html:133
985 #: rhodecode/templates/base/base.html:291
986 #: rhodecode/templates/settings/repo_fork.html:13
987 msgid "fork"
988 msgstr ""
989
990 #: rhodecode/templates/index_base.html:134
991 #: rhodecode/templates/admin/repos/repos.html:60
992 #: rhodecode/templates/admin/users/user_edit_my_account.html:143
993 #: rhodecode/templates/summary/summary.html:69
994 #: rhodecode/templates/summary/summary.html:71
995 msgid "Fork of"
996 msgstr ""
997
998 #: rhodecode/templates/index_base.html:155
999 #: rhodecode/templates/admin/repos/repos.html:73
1000 msgid "No changesets yet"
1001 msgstr ""
1002
1003 #: rhodecode/templates/index_base.html:161
1004 #: rhodecode/templates/index_base.html:163
1005 #, python-format
1328 #, python-format
1006 msgid "Subscribe to %s rss feed"
1329 msgid "Subscribe to %s rss feed"
1007 msgstr ""
1330 msgstr ""
1008
1331
1009 #: rhodecode/templates/index_base.html:168
1332 #: rhodecode/templates/index_base.html:117
1010 #: rhodecode/templates/index_base.html:170
1333 #: rhodecode/templates/index_base.html:119
1011 #, python-format
1334 #, python-format
1012 msgid "Subscribe to %s atom feed"
1335 msgid "Subscribe to %s atom feed"
1013 msgstr ""
1336 msgstr ""
1014
1337
1338 #: rhodecode/templates/index_base.html:140
1339 msgid "Group Name"
1340 msgstr ""
1341
1342 #: rhodecode/templates/index_base.html:158
1343 #: rhodecode/templates/index_base.html:198
1344 #: rhodecode/templates/admin/repos/repos.html:94
1345 #: rhodecode/templates/admin/users/user_edit_my_account.html:179
1346 #: rhodecode/templates/admin/users/users.html:107
1347 #: rhodecode/templates/bookmarks/bookmarks.html:60
1348 #: rhodecode/templates/branches/branches.html:77
1349 #: rhodecode/templates/journal/journal.html:211
1350 #: rhodecode/templates/tags/tags.html:60
1351 msgid "Click to sort ascending"
1352 msgstr ""
1353
1354 #: rhodecode/templates/index_base.html:159
1355 #: rhodecode/templates/index_base.html:199
1356 #: rhodecode/templates/admin/repos/repos.html:95
1357 #: rhodecode/templates/admin/users/user_edit_my_account.html:180
1358 #: rhodecode/templates/admin/users/users.html:108
1359 #: rhodecode/templates/bookmarks/bookmarks.html:61
1360 #: rhodecode/templates/branches/branches.html:78
1361 #: rhodecode/templates/journal/journal.html:212
1362 #: rhodecode/templates/tags/tags.html:61
1363 msgid "Click to sort descending"
1364 msgstr ""
1365
1366 #: rhodecode/templates/index_base.html:169
1367 msgid "Last Change"
1368 msgstr ""
1369
1370 #: rhodecode/templates/index_base.html:200
1371 #: rhodecode/templates/admin/repos/repos.html:96
1372 #: rhodecode/templates/admin/users/user_edit_my_account.html:181
1373 #: rhodecode/templates/admin/users/users.html:109
1374 #: rhodecode/templates/bookmarks/bookmarks.html:62
1375 #: rhodecode/templates/branches/branches.html:79
1376 #: rhodecode/templates/journal/journal.html:213
1377 #: rhodecode/templates/tags/tags.html:62
1378 msgid "No records found."
1379 msgstr ""
1380
1381 #: rhodecode/templates/index_base.html:201
1382 #: rhodecode/templates/admin/repos/repos.html:97
1383 #: rhodecode/templates/admin/users/user_edit_my_account.html:182
1384 #: rhodecode/templates/admin/users/users.html:110
1385 #: rhodecode/templates/bookmarks/bookmarks.html:63
1386 #: rhodecode/templates/branches/branches.html:80
1387 #: rhodecode/templates/journal/journal.html:214
1388 #: rhodecode/templates/tags/tags.html:63
1389 msgid "Data error."
1390 msgstr ""
1391
1392 #: rhodecode/templates/index_base.html:202
1393 #: rhodecode/templates/admin/repos/repos.html:98
1394 #: rhodecode/templates/admin/users/user_edit_my_account.html:183
1395 #: rhodecode/templates/admin/users/users.html:111
1396 #: rhodecode/templates/bookmarks/bookmarks.html:64
1397 #: rhodecode/templates/branches/branches.html:81
1398 #: rhodecode/templates/journal/journal.html:215
1399 #: rhodecode/templates/tags/tags.html:64
1400 msgid "Loading..."
1401 msgstr ""
1402
1015 #: rhodecode/templates/login.html:5 rhodecode/templates/login.html:54
1403 #: rhodecode/templates/login.html:5 rhodecode/templates/login.html:54
1016 #: rhodecode/templates/base/base.html:38
1017 msgid "Sign In"
1404 msgid "Sign In"
1018 msgstr ""
1405 msgstr ""
1019
1406
@@ -1024,25 +1411,29 b' msgstr ""'
1024 #: rhodecode/templates/login.html:31 rhodecode/templates/register.html:20
1411 #: rhodecode/templates/login.html:31 rhodecode/templates/register.html:20
1025 #: rhodecode/templates/admin/admin_log.html:5
1412 #: rhodecode/templates/admin/admin_log.html:5
1026 #: rhodecode/templates/admin/users/user_add.html:32
1413 #: rhodecode/templates/admin/users/user_add.html:32
1027 #: rhodecode/templates/admin/users/user_edit.html:47
1414 #: rhodecode/templates/admin/users/user_edit.html:50
1028 #: rhodecode/templates/admin/users/user_edit_my_account.html:45
1415 #: rhodecode/templates/admin/users/user_edit_my_account_form.html:26
1029 #: rhodecode/templates/base/base.html:15
1416 #: rhodecode/templates/base/base.html:83
1030 #: rhodecode/templates/summary/summary.html:106
1417 #: rhodecode/templates/summary/summary.html:122
1031 msgid "Username"
1418 msgid "Username"
1032 msgstr ""
1419 msgstr ""
1033
1420
1034 #: rhodecode/templates/login.html:40 rhodecode/templates/register.html:29
1421 #: rhodecode/templates/login.html:40 rhodecode/templates/register.html:29
1035 #: rhodecode/templates/admin/ldap/ldap.html:46
1422 #: rhodecode/templates/admin/ldap/ldap.html:46
1036 #: rhodecode/templates/admin/users/user_add.html:41
1423 #: rhodecode/templates/admin/users/user_add.html:41
1037 #: rhodecode/templates/base/base.html:24
1424 #: rhodecode/templates/base/base.html:92
1038 msgid "Password"
1425 msgid "Password"
1039 msgstr ""
1426 msgstr ""
1040
1427
1428 #: rhodecode/templates/login.html:50
1429 msgid "Remember me"
1430 msgstr ""
1431
1041 #: rhodecode/templates/login.html:60
1432 #: rhodecode/templates/login.html:60
1042 msgid "Forgot your password ?"
1433 msgid "Forgot your password ?"
1043 msgstr ""
1434 msgstr ""
1044
1435
1045 #: rhodecode/templates/login.html:63 rhodecode/templates/base/base.html:35
1436 #: rhodecode/templates/login.html:63 rhodecode/templates/base/base.html:103
1046 msgid "Don't have an account ?"
1437 msgid "Don't have an account ?"
1047 msgstr ""
1438 msgstr ""
1048
1439
@@ -1079,24 +1470,24 b' msgid "Re-enter password"'
1079 msgstr ""
1470 msgstr ""
1080
1471
1081 #: rhodecode/templates/register.html:47
1472 #: rhodecode/templates/register.html:47
1082 #: rhodecode/templates/admin/users/user_add.html:50
1473 #: rhodecode/templates/admin/users/user_add.html:59
1083 #: rhodecode/templates/admin/users/user_edit.html:74
1474 #: rhodecode/templates/admin/users/user_edit.html:86
1084 #: rhodecode/templates/admin/users/user_edit_my_account.html:63
1475 #: rhodecode/templates/admin/users/user_edit_my_account_form.html:53
1085 msgid "First Name"
1476 msgid "First Name"
1086 msgstr ""
1477 msgstr ""
1087
1478
1088 #: rhodecode/templates/register.html:56
1479 #: rhodecode/templates/register.html:56
1089 #: rhodecode/templates/admin/users/user_add.html:59
1480 #: rhodecode/templates/admin/users/user_add.html:68
1090 #: rhodecode/templates/admin/users/user_edit.html:83
1481 #: rhodecode/templates/admin/users/user_edit.html:95
1091 #: rhodecode/templates/admin/users/user_edit_my_account.html:72
1482 #: rhodecode/templates/admin/users/user_edit_my_account_form.html:62
1092 msgid "Last Name"
1483 msgid "Last Name"
1093 msgstr ""
1484 msgstr ""
1094
1485
1095 #: rhodecode/templates/register.html:65
1486 #: rhodecode/templates/register.html:65
1096 #: rhodecode/templates/admin/users/user_add.html:68
1487 #: rhodecode/templates/admin/users/user_add.html:77
1097 #: rhodecode/templates/admin/users/user_edit.html:92
1488 #: rhodecode/templates/admin/users/user_edit.html:104
1098 #: rhodecode/templates/admin/users/user_edit_my_account.html:81
1489 #: rhodecode/templates/admin/users/user_edit_my_account_form.html:71
1099 #: rhodecode/templates/summary/summary.html:108
1490 #: rhodecode/templates/summary/summary.html:124
1100 msgid "Email"
1491 msgid "Email"
1101 msgstr ""
1492 msgstr ""
1102
1493
@@ -1108,20 +1499,59 b' msgstr ""'
1108 msgid "Your account must wait for activation by administrator"
1499 msgid "Your account must wait for activation by administrator"
1109 msgstr ""
1500 msgstr ""
1110
1501
1111 #: rhodecode/templates/repo_switcher_list.html:14
1502 #: rhodecode/templates/repo_switcher_list.html:11
1503 #: rhodecode/templates/admin/repos/repo_add_base.html:65
1504 #: rhodecode/templates/admin/repos/repo_edit.html:85
1505 #: rhodecode/templates/settings/repo_settings.html:76
1112 msgid "Private repository"
1506 msgid "Private repository"
1113 msgstr ""
1507 msgstr ""
1114
1508
1115 #: rhodecode/templates/repo_switcher_list.html:19
1509 #: rhodecode/templates/repo_switcher_list.html:16
1116 msgid "Public repository"
1510 msgid "Public repository"
1117 msgstr ""
1511 msgstr ""
1118
1512
1513 #: rhodecode/templates/switch_to_list.html:3
1514 #: rhodecode/templates/branches/branches.html:14
1515 msgid "branches"
1516 msgstr ""
1517
1518 #: rhodecode/templates/switch_to_list.html:10
1519 #: rhodecode/templates/branches/branches_data.html:57
1520 msgid "There are no branches yet"
1521 msgstr ""
1522
1523 #: rhodecode/templates/switch_to_list.html:15
1524 #: rhodecode/templates/shortlog/shortlog_data.html:10
1525 #: rhodecode/templates/tags/tags.html:15
1526 msgid "tags"
1527 msgstr ""
1528
1529 #: rhodecode/templates/switch_to_list.html:22
1530 #: rhodecode/templates/tags/tags_data.html:33
1531 msgid "There are no tags yet"
1532 msgstr ""
1533
1534 #: rhodecode/templates/switch_to_list.html:28
1535 #: rhodecode/templates/bookmarks/bookmarks.html:15
1536 msgid "bookmarks"
1537 msgstr ""
1538
1539 #: rhodecode/templates/switch_to_list.html:35
1540 #: rhodecode/templates/bookmarks/bookmarks_data.html:32
1541 msgid "There are no bookmarks yet"
1542 msgstr ""
1543
1119 #: rhodecode/templates/admin/admin.html:5
1544 #: rhodecode/templates/admin/admin.html:5
1120 #: rhodecode/templates/admin/admin.html:9
1545 #: rhodecode/templates/admin/admin.html:9
1121 msgid "Admin journal"
1546 msgid "Admin journal"
1122 msgstr ""
1547 msgstr ""
1123
1548
1124 #: rhodecode/templates/admin/admin_log.html:6
1549 #: rhodecode/templates/admin/admin_log.html:6
1550 #: rhodecode/templates/admin/repos/repos.html:74
1551 #: rhodecode/templates/admin/users/user_edit_my_account_repos.html:8
1552 #: rhodecode/templates/admin/users/user_edit_my_account_repos.html:9
1553 #: rhodecode/templates/journal/journal.html:61
1554 #: rhodecode/templates/journal/journal.html:62
1125 msgid "Action"
1555 msgid "Action"
1126 msgstr ""
1556 msgstr ""
1127
1557
@@ -1130,6 +1560,11 b' msgid "Repository"'
1130 msgstr ""
1560 msgstr ""
1131
1561
1132 #: rhodecode/templates/admin/admin_log.html:8
1562 #: rhodecode/templates/admin/admin_log.html:8
1563 #: rhodecode/templates/bookmarks/bookmarks.html:37
1564 #: rhodecode/templates/bookmarks/bookmarks_data.html:7
1565 #: rhodecode/templates/branches/branches.html:52
1566 #: rhodecode/templates/tags/tags.html:37
1567 #: rhodecode/templates/tags/tags_data.html:7
1133 msgid "Date"
1568 msgid "Date"
1134 msgstr ""
1569 msgstr ""
1135
1570
@@ -1137,7 +1572,7 b' msgstr ""'
1137 msgid "From IP"
1572 msgid "From IP"
1138 msgstr ""
1573 msgstr ""
1139
1574
1140 #: rhodecode/templates/admin/admin_log.html:52
1575 #: rhodecode/templates/admin/admin_log.html:53
1141 msgid "No actions yet"
1576 msgid "No actions yet"
1142 msgstr ""
1577 msgstr ""
1143
1578
@@ -1214,23 +1649,64 b' msgid "E-mail Attribute"'
1214 msgstr ""
1649 msgstr ""
1215
1650
1216 #: rhodecode/templates/admin/ldap/ldap.html:89
1651 #: rhodecode/templates/admin/ldap/ldap.html:89
1652 #: rhodecode/templates/admin/repos/repo_edit.html:141
1653 #: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:74
1217 #: rhodecode/templates/admin/settings/hooks.html:73
1654 #: rhodecode/templates/admin/settings/hooks.html:73
1218 #: rhodecode/templates/admin/users/user_edit.html:117
1655 #: rhodecode/templates/admin/users/user_edit.html:129
1219 #: rhodecode/templates/admin/users/user_edit.html:142
1656 #: rhodecode/templates/admin/users/user_edit.html:174
1220 #: rhodecode/templates/admin/users/user_edit_my_account.html:89
1657 #: rhodecode/templates/admin/users/user_edit_my_account_form.html:79
1221 #: rhodecode/templates/admin/users_groups/users_group_edit.html:263
1658 #: rhodecode/templates/admin/users_groups/users_group_edit.html:135
1659 #: rhodecode/templates/settings/repo_settings.html:93
1222 msgid "Save"
1660 msgid "Save"
1223 msgstr ""
1661 msgstr ""
1224
1662
1663 #: rhodecode/templates/admin/notifications/notifications.html:5
1664 #: rhodecode/templates/admin/notifications/notifications.html:9
1665 msgid "My Notifications"
1666 msgstr ""
1667
1668 #: rhodecode/templates/admin/notifications/notifications.html:29
1669 msgid "All"
1670 msgstr ""
1671
1672 #: rhodecode/templates/admin/notifications/notifications.html:30
1673 #, fuzzy
1674 msgid "Comments"
1675 msgstr ""
1676
1677 #: rhodecode/templates/admin/notifications/notifications.html:31
1678 #: rhodecode/templates/base/base.html:254
1679 #: rhodecode/templates/base/base.html:256
1680 msgid "Pull requests"
1681 msgstr ""
1682
1683 #: rhodecode/templates/admin/notifications/notifications.html:35
1684 msgid "Mark all read"
1685 msgstr ""
1686
1687 #: rhodecode/templates/admin/notifications/notifications_data.html:39
1688 msgid "No notifications here yet"
1689 msgstr ""
1690
1691 #: rhodecode/templates/admin/notifications/show_notification.html:5
1692 #: rhodecode/templates/admin/notifications/show_notification.html:11
1693 msgid "Show notification"
1694 msgstr ""
1695
1696 #: rhodecode/templates/admin/notifications/show_notification.html:9
1697 msgid "Notifications"
1698 msgstr ""
1699
1225 #: rhodecode/templates/admin/permissions/permissions.html:5
1700 #: rhodecode/templates/admin/permissions/permissions.html:5
1226 msgid "Permissions administration"
1701 msgid "Permissions administration"
1227 msgstr ""
1702 msgstr ""
1228
1703
1229 #: rhodecode/templates/admin/permissions/permissions.html:11
1704 #: rhodecode/templates/admin/permissions/permissions.html:11
1230 #: rhodecode/templates/admin/repos/repo_edit.html:109
1705 #: rhodecode/templates/admin/repos/repo_edit.html:134
1231 #: rhodecode/templates/admin/users/user_edit.html:127
1706 #: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:58
1232 #: rhodecode/templates/admin/users_groups/users_group_edit.html:248
1707 #: rhodecode/templates/admin/users/user_edit.html:139
1233 #: rhodecode/templates/settings/repo_settings.html:58
1708 #: rhodecode/templates/admin/users_groups/users_group_edit.html:100
1709 #: rhodecode/templates/settings/repo_settings.html:86
1234 msgid "Permissions"
1710 msgid "Permissions"
1235 msgstr ""
1711 msgstr ""
1236
1712
@@ -1266,6 +1742,11 b' msgid "Repository creation"'
1266 msgstr ""
1742 msgstr ""
1267
1743
1268 #: rhodecode/templates/admin/permissions/permissions.html:71
1744 #: rhodecode/templates/admin/permissions/permissions.html:71
1745 msgid "Repository forking"
1746 msgstr ""
1747
1748 #: rhodecode/templates/admin/permissions/permissions.html:78
1749 #: rhodecode/templates/admin/repos/repo_edit.html:241
1269 msgid "set"
1750 msgid "set"
1270 msgstr ""
1751 msgstr ""
1271
1752
@@ -1276,7 +1757,6 b' msgstr ""'
1276
1757
1277 #: rhodecode/templates/admin/repos/repo_add.html:11
1758 #: rhodecode/templates/admin/repos/repo_add.html:11
1278 #: rhodecode/templates/admin/repos/repo_edit.html:11
1759 #: rhodecode/templates/admin/repos/repo_edit.html:11
1279 #: rhodecode/templates/admin/repos/repos.html:10
1280 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:10
1760 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:10
1281 msgid "Repositories"
1761 msgid "Repositories"
1282 msgstr ""
1762 msgstr ""
@@ -1286,30 +1766,70 b' msgid "add new"'
1286 msgstr ""
1766 msgstr ""
1287
1767
1288 #: rhodecode/templates/admin/repos/repo_add_base.html:20
1768 #: rhodecode/templates/admin/repos/repo_add_base.html:20
1289 #: rhodecode/templates/summary/summary.html:80
1769 #: rhodecode/templates/summary/summary.html:95
1290 #: rhodecode/templates/summary/summary.html:82
1770 #: rhodecode/templates/summary/summary.html:96
1291 msgid "Clone from"
1771 msgid "Clone from"
1292 msgstr ""
1772 msgstr ""
1293
1773
1294 #: rhodecode/templates/admin/repos/repo_add_base.html:28
1774 #: rhodecode/templates/admin/repos/repo_add_base.html:24
1295 #: rhodecode/templates/admin/repos/repo_edit.html:48
1775 #: rhodecode/templates/admin/repos/repo_edit.html:44
1776 #: rhodecode/templates/settings/repo_settings.html:43
1777 msgid "Optional http[s] url from which repository should be cloned."
1778 msgstr ""
1779
1780 #: rhodecode/templates/admin/repos/repo_add_base.html:29
1781 #: rhodecode/templates/admin/repos/repo_edit.html:49
1296 #: rhodecode/templates/admin/repos_groups/repos_groups.html:4
1782 #: rhodecode/templates/admin/repos_groups/repos_groups.html:4
1783 #: rhodecode/templates/forks/fork.html:50
1784 #: rhodecode/templates/settings/repo_settings.html:48
1297 msgid "Repository group"
1785 msgid "Repository group"
1298 msgstr ""
1786 msgstr ""
1299
1787
1300 #: rhodecode/templates/admin/repos/repo_add_base.html:36
1788 #: rhodecode/templates/admin/repos/repo_add_base.html:33
1301 #: rhodecode/templates/admin/repos/repo_edit.html:56
1789 #: rhodecode/templates/forks/fork.html:54
1790 msgid "Optionaly select a group to put this repository into."
1791 msgstr ""
1792
1793 #: rhodecode/templates/admin/repos/repo_add_base.html:38
1794 #: rhodecode/templates/admin/repos/repo_edit.html:58
1302 msgid "Type"
1795 msgid "Type"
1303 msgstr ""
1796 msgstr ""
1304
1797
1305 #: rhodecode/templates/admin/repos/repo_add_base.html:52
1798 #: rhodecode/templates/admin/repos/repo_add_base.html:42
1306 #: rhodecode/templates/admin/repos/repo_edit.html:73
1799 msgid "Type of repository to create."
1307 #: rhodecode/templates/settings/repo_fork.html:48
1800 msgstr ""
1308 #: rhodecode/templates/settings/repo_settings.html:49
1801
1309 msgid "Private"
1802 #: rhodecode/templates/admin/repos/repo_add_base.html:47
1310 msgstr ""
1803 #: rhodecode/templates/admin/repos/repo_edit.html:66
1311
1804 #: rhodecode/templates/forks/fork.html:41
1312 #: rhodecode/templates/admin/repos/repo_add_base.html:59
1805 #: rhodecode/templates/settings/repo_settings.html:57
1806 msgid "Landing revision"
1807 msgstr ""
1808
1809 #: rhodecode/templates/admin/repos/repo_add_base.html:51
1810 #: rhodecode/templates/admin/repos/repo_edit.html:70
1811 #: rhodecode/templates/forks/fork.html:45
1812 #: rhodecode/templates/settings/repo_settings.html:61
1813 msgid "Default revision for files page, downloads, whoosh and readme"
1814 msgstr ""
1815
1816 #: rhodecode/templates/admin/repos/repo_add_base.html:60
1817 #: rhodecode/templates/admin/repos/repo_edit.html:79
1818 #: rhodecode/templates/forks/fork.html:63
1819 #: rhodecode/templates/settings/repo_settings.html:70
1820 msgid "Keep it short and to the point. Use a README file for longer descriptions."
1821 msgstr ""
1822
1823 #: rhodecode/templates/admin/repos/repo_add_base.html:69
1824 #: rhodecode/templates/admin/repos/repo_edit.html:89
1825 #: rhodecode/templates/forks/fork.html:72
1826 #: rhodecode/templates/settings/repo_settings.html:80
1827 msgid ""
1828 "Private repositories are only visible to people explicitly added as "
1829 "collaborators."
1830 msgstr ""
1831
1832 #: rhodecode/templates/admin/repos/repo_add_base.html:73
1313 msgid "add"
1833 msgid "add"
1314 msgstr ""
1834 msgstr ""
1315
1835
@@ -1323,183 +1843,269 b' msgstr ""'
1323
1843
1324 #: rhodecode/templates/admin/repos/repo_edit.html:13
1844 #: rhodecode/templates/admin/repos/repo_edit.html:13
1325 #: rhodecode/templates/admin/users/user_edit.html:13
1845 #: rhodecode/templates/admin/users/user_edit.html:13
1326 #: rhodecode/templates/admin/users/user_edit_my_account.html:148
1846 #: rhodecode/templates/admin/users/user_edit.html:224
1847 #: rhodecode/templates/admin/users/user_edit.html:226
1848 #: rhodecode/templates/admin/users/user_edit_my_account_repos.html:28
1327 #: rhodecode/templates/admin/users_groups/users_group_edit.html:13
1849 #: rhodecode/templates/admin/users_groups/users_group_edit.html:13
1328 #: rhodecode/templates/files/files_annotate.html:49
1850 #: rhodecode/templates/files/files_source.html:44
1329 #: rhodecode/templates/files/files_source.html:20
1851 #: rhodecode/templates/journal/journal.html:81
1330 msgid "edit"
1852 msgid "edit"
1331 msgstr ""
1853 msgstr ""
1332
1854
1333 #: rhodecode/templates/admin/repos/repo_edit.html:40
1855 #: rhodecode/templates/admin/repos/repo_edit.html:40
1856 #: rhodecode/templates/settings/repo_settings.html:39
1334 msgid "Clone uri"
1857 msgid "Clone uri"
1335 msgstr ""
1858 msgstr ""
1336
1859
1337 #: rhodecode/templates/admin/repos/repo_edit.html:81
1860 #: rhodecode/templates/admin/repos/repo_edit.html:53
1861 #: rhodecode/templates/settings/repo_settings.html:52
1862 msgid "Optional select a group to put this repository into."
1863 msgstr ""
1864
1865 #: rhodecode/templates/admin/repos/repo_edit.html:94
1338 msgid "Enable statistics"
1866 msgid "Enable statistics"
1339 msgstr ""
1867 msgstr ""
1340
1868
1341 #: rhodecode/templates/admin/repos/repo_edit.html:89
1869 #: rhodecode/templates/admin/repos/repo_edit.html:98
1870 msgid "Enable statistics window on summary page."
1871 msgstr ""
1872
1873 #: rhodecode/templates/admin/repos/repo_edit.html:103
1342 msgid "Enable downloads"
1874 msgid "Enable downloads"
1343 msgstr ""
1875 msgstr ""
1344
1876
1345 #: rhodecode/templates/admin/repos/repo_edit.html:127
1877 #: rhodecode/templates/admin/repos/repo_edit.html:107
1878 msgid "Enable download menu on summary page."
1879 msgstr ""
1880
1881 #: rhodecode/templates/admin/repos/repo_edit.html:112
1882 #: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:66
1883 msgid "Enable locking"
1884 msgstr ""
1885
1886 #: rhodecode/templates/admin/repos/repo_edit.html:116
1887 msgid "Enable lock-by-pulling on repository."
1888 msgstr ""
1889
1890 #: rhodecode/templates/admin/repos/repo_edit.html:126
1891 msgid "Change owner of this repository."
1892 msgstr ""
1893
1894 #: rhodecode/templates/admin/repos/repo_edit.html:142
1895 #: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:75
1896 #: rhodecode/templates/admin/settings/settings.html:113
1897 #: rhodecode/templates/admin/settings/settings.html:168
1898 #: rhodecode/templates/admin/settings/settings.html:258
1899 #: rhodecode/templates/admin/users/user_edit.html:130
1900 #: rhodecode/templates/admin/users/user_edit.html:175
1901 #: rhodecode/templates/admin/users/user_edit.html:278
1902 #: rhodecode/templates/admin/users/user_edit_my_account_form.html:80
1903 #: rhodecode/templates/admin/users_groups/users_group_edit.html:136
1904 #: rhodecode/templates/files/files_add.html:82
1905 #: rhodecode/templates/files/files_edit.html:68
1906 #: rhodecode/templates/pullrequests/pullrequest.html:124
1907 #: rhodecode/templates/settings/repo_settings.html:94
1908 msgid "Reset"
1909 msgstr ""
1910
1911 #: rhodecode/templates/admin/repos/repo_edit.html:152
1346 msgid "Administration"
1912 msgid "Administration"
1347 msgstr ""
1913 msgstr ""
1348
1914
1349 #: rhodecode/templates/admin/repos/repo_edit.html:130
1915 #: rhodecode/templates/admin/repos/repo_edit.html:155
1350 msgid "Statistics"
1916 msgid "Statistics"
1351 msgstr ""
1917 msgstr ""
1352
1918
1353 #: rhodecode/templates/admin/repos/repo_edit.html:134
1919 #: rhodecode/templates/admin/repos/repo_edit.html:159
1354 msgid "Reset current statistics"
1920 msgid "Reset current statistics"
1355 msgstr ""
1921 msgstr ""
1356
1922
1357 #: rhodecode/templates/admin/repos/repo_edit.html:134
1923 #: rhodecode/templates/admin/repos/repo_edit.html:159
1358 msgid "Confirm to remove current statistics"
1924 msgid "Confirm to remove current statistics"
1359 msgstr ""
1925 msgstr ""
1360
1926
1361 #: rhodecode/templates/admin/repos/repo_edit.html:137
1362 msgid "Fetched to rev"
1363 msgstr ""
1364
1365 #: rhodecode/templates/admin/repos/repo_edit.html:138
1366 msgid "Percentage of stats gathered"
1367 msgstr ""
1368
1369 #: rhodecode/templates/admin/repos/repo_edit.html:147
1370 msgid "Remote"
1371 msgstr ""
1372
1373 #: rhodecode/templates/admin/repos/repo_edit.html:151
1374 msgid "Pull changes from remote location"
1375 msgstr ""
1376
1377 #: rhodecode/templates/admin/repos/repo_edit.html:151
1378 msgid "Confirm to pull changes from remote side"
1379 msgstr ""
1380
1381 #: rhodecode/templates/admin/repos/repo_edit.html:162
1927 #: rhodecode/templates/admin/repos/repo_edit.html:162
1928 msgid "Fetched to rev"
1929 msgstr ""
1930
1931 #: rhodecode/templates/admin/repos/repo_edit.html:163
1932 msgid "Stats gathered"
1933 msgstr ""
1934
1935 #: rhodecode/templates/admin/repos/repo_edit.html:171
1936 msgid "Remote"
1937 msgstr ""
1938
1939 #: rhodecode/templates/admin/repos/repo_edit.html:175
1940 msgid "Pull changes from remote location"
1941 msgstr ""
1942
1943 #: rhodecode/templates/admin/repos/repo_edit.html:175
1944 msgid "Confirm to pull changes from remote side"
1945 msgstr ""
1946
1947 #: rhodecode/templates/admin/repos/repo_edit.html:186
1382 msgid "Cache"
1948 msgid "Cache"
1383 msgstr ""
1949 msgstr ""
1384
1950
1385 #: rhodecode/templates/admin/repos/repo_edit.html:166
1951 #: rhodecode/templates/admin/repos/repo_edit.html:190
1386 msgid "Invalidate repository cache"
1952 msgid "Invalidate repository cache"
1387 msgstr ""
1953 msgstr ""
1388
1954
1389 #: rhodecode/templates/admin/repos/repo_edit.html:166
1955 #: rhodecode/templates/admin/repos/repo_edit.html:190
1390 msgid "Confirm to invalidate repository cache"
1956 msgid "Confirm to invalidate repository cache"
1391 msgstr ""
1957 msgstr ""
1392
1958
1393 #: rhodecode/templates/admin/repos/repo_edit.html:177
1959 #: rhodecode/templates/admin/repos/repo_edit.html:195
1960 #: rhodecode/templates/base/base.html:318
1961 #: rhodecode/templates/base/base.html:320
1962 #: rhodecode/templates/base/base.html:322
1963 msgid "Public journal"
1964 msgstr ""
1965
1966 #: rhodecode/templates/admin/repos/repo_edit.html:201
1394 msgid "Remove from public journal"
1967 msgid "Remove from public journal"
1395 msgstr ""
1968 msgstr ""
1396
1969
1397 #: rhodecode/templates/admin/repos/repo_edit.html:179
1970 #: rhodecode/templates/admin/repos/repo_edit.html:203
1398 msgid "Add to public journal"
1971 msgid "Add to public journal"
1399 msgstr ""
1972 msgstr ""
1400
1973
1401 #: rhodecode/templates/admin/repos/repo_edit.html:185
1974 #: rhodecode/templates/admin/repos/repo_edit.html:208
1975 msgid ""
1976 "All actions made on this repository will be accessible to everyone in "
1977 "public journal"
1978 msgstr ""
1979
1980 #: rhodecode/templates/admin/repos/repo_edit.html:215
1981 msgid "Locking"
1982 msgstr ""
1983
1984 #: rhodecode/templates/admin/repos/repo_edit.html:220
1985 msgid "Unlock locked repo"
1986 msgstr ""
1987
1988 #: rhodecode/templates/admin/repos/repo_edit.html:220
1989 msgid "Confirm to unlock repository"
1990 msgstr ""
1991
1992 #: rhodecode/templates/admin/repos/repo_edit.html:223
1993 msgid "lock repo"
1994 msgstr ""
1995
1996 #: rhodecode/templates/admin/repos/repo_edit.html:223
1997 msgid "Confirm to lock repository"
1998 msgstr ""
1999
2000 #: rhodecode/templates/admin/repos/repo_edit.html:224
2001 msgid "Repository is not locked"
2002 msgstr ""
2003
2004 #: rhodecode/templates/admin/repos/repo_edit.html:229
2005 msgid "Force locking on repository. Works only when anonymous access is disabled"
2006 msgstr ""
2007
2008 #: rhodecode/templates/admin/repos/repo_edit.html:236
2009 msgid "Set as fork of"
2010 msgstr ""
2011
2012 #: rhodecode/templates/admin/repos/repo_edit.html:245
2013 msgid "Manually set this repository as a fork of another from the list"
2014 msgstr ""
2015
2016 #: rhodecode/templates/admin/repos/repo_edit.html:251
2017 #: rhodecode/templates/changeset/changeset_file_comment.html:26
1402 msgid "Delete"
2018 msgid "Delete"
1403 msgstr ""
2019 msgstr ""
1404
2020
1405 #: rhodecode/templates/admin/repos/repo_edit.html:189
2021 #: rhodecode/templates/admin/repos/repo_edit.html:255
1406 msgid "Remove this repository"
2022 msgid "Remove this repository"
1407 msgstr ""
2023 msgstr ""
1408
2024
1409 #: rhodecode/templates/admin/repos/repo_edit.html:189
2025 #: rhodecode/templates/admin/repos/repo_edit.html:255
1410 #: rhodecode/templates/admin/repos/repos.html:79
2026 #: rhodecode/templates/journal/journal.html:84
1411 msgid "Confirm to delete this repository"
2027 msgid "Confirm to delete this repository"
1412 msgstr ""
2028 msgstr ""
1413
2029
2030 #: rhodecode/templates/admin/repos/repo_edit.html:259
2031 msgid ""
2032 "This repository will be renamed in a special way in order to be "
2033 "unaccesible for RhodeCode and VCS systems.\n"
2034 " If you need fully delete it from filesystem "
2035 "please do it manually"
2036 msgstr ""
2037
1414 #: rhodecode/templates/admin/repos/repo_edit_perms.html:3
2038 #: rhodecode/templates/admin/repos/repo_edit_perms.html:3
2039 #: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:3
1415 msgid "none"
2040 msgid "none"
1416 msgstr ""
2041 msgstr ""
1417
2042
1418 #: rhodecode/templates/admin/repos/repo_edit_perms.html:4
2043 #: rhodecode/templates/admin/repos/repo_edit_perms.html:4
2044 #: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:4
1419 msgid "read"
2045 msgid "read"
1420 msgstr ""
2046 msgstr ""
1421
2047
1422 #: rhodecode/templates/admin/repos/repo_edit_perms.html:5
2048 #: rhodecode/templates/admin/repos/repo_edit_perms.html:5
2049 #: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:5
1423 msgid "write"
2050 msgid "write"
1424 msgstr ""
2051 msgstr ""
1425
2052
1426 #: rhodecode/templates/admin/repos/repo_edit_perms.html:6
2053 #: rhodecode/templates/admin/repos/repo_edit_perms.html:6
1427 #: rhodecode/templates/admin/users/users.html:38
2054 #: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:6
1428 #: rhodecode/templates/base/base.html:296
2055 #: rhodecode/templates/admin/users/users.html:85
2056 #: rhodecode/templates/base/base.html:217
1429 msgid "admin"
2057 msgid "admin"
1430 msgstr ""
2058 msgstr ""
1431
2059
1432 #: rhodecode/templates/admin/repos/repo_edit_perms.html:7
2060 #: rhodecode/templates/admin/repos/repo_edit_perms.html:7
2061 #: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:7
1433 msgid "member"
2062 msgid "member"
1434 msgstr ""
2063 msgstr ""
1435
2064
2065 #: rhodecode/templates/admin/repos/repo_edit_perms.html:16
2066 #: rhodecode/templates/data_table/_dt_elements.html:67
2067 #: rhodecode/templates/journal/journal.html:132
2068 #: rhodecode/templates/summary/summary.html:76
2069 msgid "private repository"
2070 msgstr ""
2071
2072 #: rhodecode/templates/admin/repos/repo_edit_perms.html:19
2073 #: rhodecode/templates/admin/repos/repo_edit_perms.html:28
2074 #: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:18
2075 msgid "default"
2076 msgstr ""
2077
1436 #: rhodecode/templates/admin/repos/repo_edit_perms.html:33
2078 #: rhodecode/templates/admin/repos/repo_edit_perms.html:33
1437 #: rhodecode/templates/admin/repos/repo_edit_perms.html:53
2079 #: rhodecode/templates/admin/repos/repo_edit_perms.html:58
2080 #: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:23
2081 #: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:42
1438 msgid "revoke"
2082 msgid "revoke"
1439 msgstr ""
2083 msgstr ""
1440
2084
1441 #: rhodecode/templates/admin/repos/repo_edit_perms.html:75
2085 #: rhodecode/templates/admin/repos/repo_edit_perms.html:83
2086 #: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:67
1442 msgid "Add another member"
2087 msgid "Add another member"
1443 msgstr ""
2088 msgstr ""
1444
2089
1445 #: rhodecode/templates/admin/repos/repo_edit_perms.html:89
2090 #: rhodecode/templates/admin/repos/repo_edit_perms.html:97
2091 #: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:81
1446 msgid "Failed to remove user"
2092 msgid "Failed to remove user"
1447 msgstr ""
2093 msgstr ""
1448
2094
1449 #: rhodecode/templates/admin/repos/repo_edit_perms.html:104
2095 #: rhodecode/templates/admin/repos/repo_edit_perms.html:112
2096 #: rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html:96
1450 msgid "Failed to remove users group"
2097 msgid "Failed to remove users group"
1451 msgstr ""
2098 msgstr ""
1452
2099
1453 #: rhodecode/templates/admin/repos/repo_edit_perms.html:205
1454 msgid "Group"
1455 msgstr ""
1456
1457 #: rhodecode/templates/admin/repos/repo_edit_perms.html:206
1458 #: rhodecode/templates/admin/users_groups/users_groups.html:33
1459 msgid "members"
1460 msgstr ""
1461
1462 #: rhodecode/templates/admin/repos/repos.html:5
2100 #: rhodecode/templates/admin/repos/repos.html:5
1463 msgid "Repositories administration"
2101 msgid "Repositories administration"
1464 msgstr ""
2102 msgstr ""
1465
2103
1466 #: rhodecode/templates/admin/repos/repos.html:34
1467 #: rhodecode/templates/summary/summary.html:100
1468 msgid "Contact"
1469 msgstr ""
1470
1471 #: rhodecode/templates/admin/repos/repos.html:35
1472 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:36
1473 #: rhodecode/templates/admin/users/user_edit_my_account.html:119
1474 #: rhodecode/templates/admin/users/users.html:40
1475 #: rhodecode/templates/admin/users_groups/users_groups.html:35
1476 msgid "action"
1477 msgstr ""
1478
1479 #: rhodecode/templates/admin/repos/repos.html:51
1480 #: rhodecode/templates/admin/users/user_edit_my_account.html:134
1481 #: rhodecode/templates/admin/users/user_edit_my_account.html:148
1482 msgid "private"
1483 msgstr ""
1484
1485 #: rhodecode/templates/admin/repos/repos.html:53
1486 #: rhodecode/templates/admin/repos/repos.html:59
1487 #: rhodecode/templates/admin/users/user_edit_my_account.html:136
1488 #: rhodecode/templates/admin/users/user_edit_my_account.html:142
1489 #: rhodecode/templates/summary/summary.html:68
1490 msgid "public"
1491 msgstr ""
1492
1493 #: rhodecode/templates/admin/repos/repos.html:79
1494 #: rhodecode/templates/admin/users/users.html:55
1495 msgid "delete"
1496 msgstr ""
1497
1498 #: rhodecode/templates/admin/repos_groups/repos_groups.html:8
2104 #: rhodecode/templates/admin/repos_groups/repos_groups.html:8
1499 msgid "Groups"
2105 msgid "Groups"
1500 msgstr ""
2106 msgstr ""
1501
2107
1502 #: rhodecode/templates/admin/repos_groups/repos_groups.html:13
2108 #: rhodecode/templates/admin/repos_groups/repos_groups.html:12
1503 msgid "with"
2109 msgid "with"
1504 msgstr ""
2110 msgstr ""
1505
2111
@@ -1522,10 +2128,10 b' msgid "Group parent"'
1522 msgstr ""
2128 msgstr ""
1523
2129
1524 #: rhodecode/templates/admin/repos_groups/repos_groups_add.html:58
2130 #: rhodecode/templates/admin/repos_groups/repos_groups_add.html:58
1525 #: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:58
2131 #: rhodecode/templates/admin/users/user_add.html:94
1526 #: rhodecode/templates/admin/users/user_add.html:85
1527 #: rhodecode/templates/admin/users_groups/users_group_add.html:49
2132 #: rhodecode/templates/admin/users_groups/users_group_add.html:49
1528 #: rhodecode/templates/admin/users_groups/users_group_edit.html:90
2133 #: rhodecode/templates/admin/users_groups/users_group_edit.html:90
2134 #: rhodecode/templates/pullrequests/pullrequest_show.html:113
1529 msgid "save"
2135 msgid "save"
1530 msgstr ""
2136 msgstr ""
1531
2137
@@ -1537,6 +2143,12 b' msgstr ""'
1537 msgid "edit repos group"
2143 msgid "edit repos group"
1538 msgstr ""
2144 msgstr ""
1539
2145
2146 #: rhodecode/templates/admin/repos_groups/repos_groups_edit.html:70
2147 msgid ""
2148 "Enable lock-by-pulling on group. This option will be applied to all other"
2149 " groups and repositories inside"
2150 msgstr ""
2151
1540 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5
2152 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:5
1541 msgid "Repositories groups administration"
2153 msgid "Repositories groups administration"
1542 msgstr ""
2154 msgstr ""
@@ -1546,11 +2158,26 b' msgid "ADD NEW GROUP"'
1546 msgstr ""
2158 msgstr ""
1547
2159
1548 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:35
2160 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:35
1549 msgid "Number of repositories"
2161 msgid "Number of toplevel repositories"
2162 msgstr ""
2163
2164 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:36
2165 #: rhodecode/templates/admin/users/users.html:87
2166 #: rhodecode/templates/admin/users_groups/users_groups.html:35
2167 msgid "action"
1550 msgstr ""
2168 msgstr ""
1551
2169
1552 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:54
2170 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:54
1553 msgid "Confirm to delete this group"
2171 #: rhodecode/templates/admin/users/user_edit.html:255
2172 #: rhodecode/templates/admin/users_groups/users_groups.html:44
2173 #: rhodecode/templates/data_table/_dt_elements.html:7
2174 #: rhodecode/templates/data_table/_dt_elements.html:103
2175 msgid "delete"
2176 msgstr ""
2177
2178 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:54
2179 #, python-format
2180 msgid "Confirm to delete this group: %s"
1554 msgstr ""
2181 msgstr ""
1555
2182
1556 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:62
2183 #: rhodecode/templates/admin/repos_groups/repos_groups_show.html:62
@@ -1564,7 +2191,6 b' msgstr ""'
1564
2191
1565 #: rhodecode/templates/admin/settings/hooks.html:9
2192 #: rhodecode/templates/admin/settings/hooks.html:9
1566 #: rhodecode/templates/admin/settings/settings.html:9
2193 #: rhodecode/templates/admin/settings/settings.html:9
1567 #: rhodecode/templates/settings/repo_settings.html:5
1568 #: rhodecode/templates/settings/repo_settings.html:13
2194 #: rhodecode/templates/settings/repo_settings.html:13
1569 msgid "Settings"
2195 msgid "Settings"
1570 msgstr ""
2196 msgstr ""
@@ -1604,115 +2230,185 b' msgstr ""'
1604 msgid "destroy old data"
2230 msgid "destroy old data"
1605 msgstr ""
2231 msgstr ""
1606
2232
1607 #: rhodecode/templates/admin/settings/settings.html:45
2233 #: rhodecode/templates/admin/settings/settings.html:41
2234 msgid ""
2235 "Rescan repositories location for new repositories. Also deletes obsolete "
2236 "if `destroy` flag is checked "
2237 msgstr ""
2238
2239 #: rhodecode/templates/admin/settings/settings.html:46
1608 msgid "Rescan repositories"
2240 msgid "Rescan repositories"
1609 msgstr ""
2241 msgstr ""
1610
2242
1611 #: rhodecode/templates/admin/settings/settings.html:51
2243 #: rhodecode/templates/admin/settings/settings.html:52
1612 msgid "Whoosh indexing"
2244 msgid "Whoosh indexing"
1613 msgstr ""
2245 msgstr ""
1614
2246
1615 #: rhodecode/templates/admin/settings/settings.html:59
2247 #: rhodecode/templates/admin/settings/settings.html:60
1616 msgid "index build option"
2248 msgid "index build option"
1617 msgstr ""
2249 msgstr ""
1618
2250
1619 #: rhodecode/templates/admin/settings/settings.html:64
2251 #: rhodecode/templates/admin/settings/settings.html:65
1620 msgid "build from scratch"
2252 msgid "build from scratch"
1621 msgstr ""
2253 msgstr ""
1622
2254
1623 #: rhodecode/templates/admin/settings/settings.html:70
2255 #: rhodecode/templates/admin/settings/settings.html:71
1624 msgid "Reindex"
2256 msgid "Reindex"
1625 msgstr ""
2257 msgstr ""
1626
2258
1627 #: rhodecode/templates/admin/settings/settings.html:76
2259 #: rhodecode/templates/admin/settings/settings.html:77
1628 msgid "Global application settings"
2260 msgid "Global application settings"
1629 msgstr ""
2261 msgstr ""
1630
2262
1631 #: rhodecode/templates/admin/settings/settings.html:85
2263 #: rhodecode/templates/admin/settings/settings.html:86
1632 msgid "Application name"
2264 msgid "Application name"
1633 msgstr ""
2265 msgstr ""
1634
2266
1635 #: rhodecode/templates/admin/settings/settings.html:94
2267 #: rhodecode/templates/admin/settings/settings.html:95
1636 msgid "Realm text"
2268 msgid "Realm text"
1637 msgstr ""
2269 msgstr ""
1638
2270
1639 #: rhodecode/templates/admin/settings/settings.html:103
2271 #: rhodecode/templates/admin/settings/settings.html:104
1640 msgid "GA code"
2272 msgid "GA code"
1641 msgstr ""
2273 msgstr ""
1642
2274
1643 #: rhodecode/templates/admin/settings/settings.html:111
1644 #: rhodecode/templates/admin/settings/settings.html:177
1645 msgid "Save settings"
1646 msgstr ""
1647
1648 #: rhodecode/templates/admin/settings/settings.html:112
2275 #: rhodecode/templates/admin/settings/settings.html:112
1649 #: rhodecode/templates/admin/settings/settings.html:178
2276 #: rhodecode/templates/admin/settings/settings.html:167
1650 #: rhodecode/templates/admin/users/user_edit.html:118
2277 #: rhodecode/templates/admin/settings/settings.html:257
1651 #: rhodecode/templates/admin/users/user_edit.html:143
2278 msgid "Save settings"
1652 #: rhodecode/templates/admin/users/user_edit_my_account.html:90
2279 msgstr ""
1653 #: rhodecode/templates/admin/users_groups/users_group_edit.html:264
2280
1654 #: rhodecode/templates/files/files_edit.html:50
2281 #: rhodecode/templates/admin/settings/settings.html:119
1655 msgid "Reset"
2282 msgid "Visualisation settings"
1656 msgstr ""
2283 msgstr ""
1657
2284
1658 #: rhodecode/templates/admin/settings/settings.html:118
2285 #: rhodecode/templates/admin/settings/settings.html:128
1659 msgid "Mercurial settings"
2286 msgid "Icons"
1660 msgstr ""
2287 msgstr ""
1661
2288
1662 #: rhodecode/templates/admin/settings/settings.html:127
2289 #: rhodecode/templates/admin/settings/settings.html:133
2290 msgid "Show public repo icon on repositories"
2291 msgstr ""
2292
2293 #: rhodecode/templates/admin/settings/settings.html:137
2294 msgid "Show private repo icon on repositories"
2295 msgstr ""
2296
2297 #: rhodecode/templates/admin/settings/settings.html:144
2298 msgid "Meta-Tagging"
2299 msgstr ""
2300
2301 #: rhodecode/templates/admin/settings/settings.html:149
2302 msgid "Stylify recognised metatags:"
2303 msgstr ""
2304
2305 #: rhodecode/templates/admin/settings/settings.html:176
2306 msgid "VCS settings"
2307 msgstr ""
2308
2309 #: rhodecode/templates/admin/settings/settings.html:185
1663 msgid "Web"
2310 msgid "Web"
1664 msgstr ""
2311 msgstr ""
1665
2312
1666 #: rhodecode/templates/admin/settings/settings.html:132
2313 #: rhodecode/templates/admin/settings/settings.html:190
1667 msgid "require ssl for pushing"
2314 msgid "require ssl for vcs operations"
1668 msgstr ""
2315 msgstr ""
1669
2316
1670 #: rhodecode/templates/admin/settings/settings.html:139
2317 #: rhodecode/templates/admin/settings/settings.html:192
2318 msgid ""
2319 "RhodeCode will require SSL for pushing or pulling. If SSL is missing it "
2320 "will return HTTP Error 406: Not Acceptable"
2321 msgstr ""
2322
2323 #: rhodecode/templates/admin/settings/settings.html:198
1671 msgid "Hooks"
2324 msgid "Hooks"
1672 msgstr ""
2325 msgstr ""
1673
2326
1674 #: rhodecode/templates/admin/settings/settings.html:142
2327 #: rhodecode/templates/admin/settings/settings.html:203
1675 msgid "advanced setup"
1676 msgstr ""
1677
1678 #: rhodecode/templates/admin/settings/settings.html:147
1679 msgid "Update repository after push (hg update)"
2328 msgid "Update repository after push (hg update)"
1680 msgstr ""
2329 msgstr ""
1681
2330
1682 #: rhodecode/templates/admin/settings/settings.html:151
2331 #: rhodecode/templates/admin/settings/settings.html:207
1683 msgid "Show repository size after push"
2332 msgid "Show repository size after push"
1684 msgstr ""
2333 msgstr ""
1685
2334
1686 #: rhodecode/templates/admin/settings/settings.html:155
2335 #: rhodecode/templates/admin/settings/settings.html:211
1687 msgid "Log user push commands"
2336 msgid "Log user push commands"
1688 msgstr ""
2337 msgstr ""
1689
2338
1690 #: rhodecode/templates/admin/settings/settings.html:159
2339 #: rhodecode/templates/admin/settings/settings.html:215
1691 msgid "Log user pull commands"
2340 msgid "Log user pull commands"
1692 msgstr ""
2341 msgstr ""
1693
2342
1694 #: rhodecode/templates/admin/settings/settings.html:166
2343 #: rhodecode/templates/admin/settings/settings.html:219
2344 msgid "advanced setup"
2345 msgstr ""
2346
2347 #: rhodecode/templates/admin/settings/settings.html:224
2348 msgid "Mercurial Extensions"
2349 msgstr ""
2350
2351 #: rhodecode/templates/admin/settings/settings.html:229
2352 msgid "largefiles extensions"
2353 msgstr ""
2354
2355 #: rhodecode/templates/admin/settings/settings.html:233
2356 msgid "hgsubversion extensions"
2357 msgstr ""
2358
2359 #: rhodecode/templates/admin/settings/settings.html:235
2360 msgid ""
2361 "Requires hgsubversion library installed. Allows clonning from svn remote "
2362 "locations"
2363 msgstr ""
2364
2365 #: rhodecode/templates/admin/settings/settings.html:245
1695 msgid "Repositories location"
2366 msgid "Repositories location"
1696 msgstr ""
2367 msgstr ""
1697
2368
1698 #: rhodecode/templates/admin/settings/settings.html:171
2369 #: rhodecode/templates/admin/settings/settings.html:250
1699 msgid ""
2370 msgid ""
1700 "This a crucial application setting. If you are really sure you need to "
2371 "This a crucial application setting. If you are really sure you need to "
1701 "change this, you must restart application in order to make this setting "
2372 "change this, you must restart application in order to make this setting "
1702 "take effect. Click this label to unlock."
2373 "take effect. Click this label to unlock."
1703 msgstr ""
2374 msgstr ""
1704
2375
1705 #: rhodecode/templates/admin/settings/settings.html:172
2376 #: rhodecode/templates/admin/settings/settings.html:251
1706 msgid "unlock"
2377 msgid "unlock"
1707 msgstr ""
2378 msgstr ""
1708
2379
2380 #: rhodecode/templates/admin/settings/settings.html:252
2381 msgid ""
2382 "Location where repositories are stored. After changing this value a "
2383 "restart, and rescan is required"
2384 msgstr ""
2385
2386 #: rhodecode/templates/admin/settings/settings.html:272
2387 msgid "Test Email"
2388 msgstr ""
2389
2390 #: rhodecode/templates/admin/settings/settings.html:280
2391 msgid "Email to"
2392 msgstr ""
2393
2394 #: rhodecode/templates/admin/settings/settings.html:288
2395 msgid "Send"
2396 msgstr ""
2397
2398 #: rhodecode/templates/admin/settings/settings.html:294
2399 msgid "System Info and Packages"
2400 msgstr ""
2401
2402 #: rhodecode/templates/admin/settings/settings.html:297
2403 msgid "show"
2404 msgstr ""
2405
1709 #: rhodecode/templates/admin/users/user_add.html:5
2406 #: rhodecode/templates/admin/users/user_add.html:5
1710 msgid "Add user"
2407 msgid "Add user"
1711 msgstr ""
2408 msgstr ""
1712
2409
1713 #: rhodecode/templates/admin/users/user_add.html:10
2410 #: rhodecode/templates/admin/users/user_add.html:10
1714 #: rhodecode/templates/admin/users/user_edit.html:11
2411 #: rhodecode/templates/admin/users/user_edit.html:11
1715 #: rhodecode/templates/admin/users/users.html:9
1716 msgid "Users"
2412 msgid "Users"
1717 msgstr ""
2413 msgstr ""
1718
2414
@@ -1720,8 +2416,12 b' msgstr ""'
1720 msgid "add new user"
2416 msgid "add new user"
1721 msgstr ""
2417 msgstr ""
1722
2418
1723 #: rhodecode/templates/admin/users/user_add.html:77
2419 #: rhodecode/templates/admin/users/user_add.html:50
1724 #: rhodecode/templates/admin/users/user_edit.html:101
2420 msgid "Password confirmation"
2421 msgstr ""
2422
2423 #: rhodecode/templates/admin/users/user_add.html:86
2424 #: rhodecode/templates/admin/users/user_edit.html:113
1725 #: rhodecode/templates/admin/users_groups/users_group_add.html:41
2425 #: rhodecode/templates/admin/users_groups/users_group_add.html:41
1726 #: rhodecode/templates/admin/users_groups/users_group_edit.html:42
2426 #: rhodecode/templates/admin/users_groups/users_group_edit.html:42
1727 msgid "Active"
2427 msgid "Active"
@@ -1731,36 +2431,93 b' msgstr ""'
1731 msgid "Edit user"
2431 msgid "Edit user"
1732 msgstr ""
2432 msgstr ""
1733
2433
1734 #: rhodecode/templates/admin/users/user_edit.html:33
2434 #: rhodecode/templates/admin/users/user_edit.html:34
1735 #: rhodecode/templates/admin/users/user_edit_my_account.html:32
2435 #: rhodecode/templates/admin/users/user_edit_my_account_form.html:10
1736 msgid "Change your avatar at"
2436 msgid "Change your avatar at"
1737 msgstr ""
2437 msgstr ""
1738
2438
1739 #: rhodecode/templates/admin/users/user_edit.html:34
2439 #: rhodecode/templates/admin/users/user_edit.html:35
1740 #: rhodecode/templates/admin/users/user_edit_my_account.html:33
2440 #: rhodecode/templates/admin/users/user_edit_my_account_form.html:11
1741 msgid "Using"
2441 msgid "Using"
1742 msgstr ""
2442 msgstr ""
1743
2443
1744 #: rhodecode/templates/admin/users/user_edit.html:40
2444 #: rhodecode/templates/admin/users/user_edit.html:43
1745 #: rhodecode/templates/admin/users/user_edit_my_account.html:39
2445 #: rhodecode/templates/admin/users/user_edit_my_account_form.html:20
1746 msgid "API key"
2446 msgid "API key"
1747 msgstr ""
2447 msgstr ""
1748
2448
1749 #: rhodecode/templates/admin/users/user_edit.html:56
2449 #: rhodecode/templates/admin/users/user_edit.html:59
1750 msgid "LDAP DN"
2450 msgid "LDAP DN"
1751 msgstr ""
2451 msgstr ""
1752
2452
1753 #: rhodecode/templates/admin/users/user_edit.html:65
2453 #: rhodecode/templates/admin/users/user_edit.html:68
1754 #: rhodecode/templates/admin/users/user_edit_my_account.html:54
2454 #: rhodecode/templates/admin/users/user_edit_my_account_form.html:35
1755 msgid "New password"
2455 msgid "New password"
1756 msgstr ""
2456 msgstr ""
1757
2457
1758 #: rhodecode/templates/admin/users/user_edit.html:135
2458 #: rhodecode/templates/admin/users/user_edit.html:77
1759 #: rhodecode/templates/admin/users_groups/users_group_edit.html:256
2459 #: rhodecode/templates/admin/users/user_edit_my_account_form.html:44
2460 msgid "New password confirmation"
2461 msgstr ""
2462
2463 #: rhodecode/templates/admin/users/user_edit.html:147
2464 #: rhodecode/templates/admin/users_groups/users_group_edit.html:108
2465 msgid "Inherit default permissions"
2466 msgstr ""
2467
2468 #: rhodecode/templates/admin/users/user_edit.html:152
2469 #: rhodecode/templates/admin/users_groups/users_group_edit.html:113
2470 #, python-format
2471 msgid ""
2472 "Select to inherit permissions from %s settings. With this selected below "
2473 "options does not have any action"
2474 msgstr ""
2475
2476 #: rhodecode/templates/admin/users/user_edit.html:158
2477 #: rhodecode/templates/admin/users_groups/users_group_edit.html:119
1760 msgid "Create repositories"
2478 msgid "Create repositories"
1761 msgstr ""
2479 msgstr ""
1762
2480
2481 #: rhodecode/templates/admin/users/user_edit.html:166
2482 #: rhodecode/templates/admin/users_groups/users_group_edit.html:127
2483 msgid "Fork repositories"
2484 msgstr ""
2485
2486 #: rhodecode/templates/admin/users/user_edit.html:186
2487 #: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:22
2488 #: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:39
2489 msgid "Nothing here yet"
2490 msgstr ""
2491
2492 #: rhodecode/templates/admin/users/user_edit.html:193
2493 #: rhodecode/templates/admin/users/user_edit_my_account.html:60
2494 #: rhodecode/templates/admin/users/user_edit_my_account.html:194
2495 msgid "Permission"
2496 msgstr ""
2497
2498 #: rhodecode/templates/admin/users/user_edit.html:194
2499 msgid "Edit Permission"
2500 msgstr ""
2501
2502 #: rhodecode/templates/admin/users/user_edit.html:243
2503 msgid "Email addresses"
2504 msgstr ""
2505
2506 #: rhodecode/templates/admin/users/user_edit.html:256
2507 #, python-format
2508 msgid "Confirm to delete this email: %s"
2509 msgstr ""
2510
2511 #: rhodecode/templates/admin/users/user_edit.html:270
2512 msgid "New email address"
2513 msgstr ""
2514
2515 #: rhodecode/templates/admin/users/user_edit.html:277
2516 msgid "Add"
2517 msgstr ""
2518
1763 #: rhodecode/templates/admin/users/user_edit_my_account.html:5
2519 #: rhodecode/templates/admin/users/user_edit_my_account.html:5
2520 #: rhodecode/templates/base/base.html:124
1764 msgid "My account"
2521 msgid "My account"
1765 msgstr ""
2522 msgstr ""
1766
2523
@@ -1768,26 +2525,74 b' msgstr ""'
1768 msgid "My Account"
2525 msgid "My Account"
1769 msgstr ""
2526 msgstr ""
1770
2527
1771 #: rhodecode/templates/admin/users/user_edit_my_account.html:101
2528 #: rhodecode/templates/admin/users/user_edit_my_account.html:35
1772 msgid "My repositories"
2529 msgid "My permissions"
1773 msgstr ""
2530 msgstr ""
1774
2531
1775 #: rhodecode/templates/admin/users/user_edit_my_account.html:107
2532 #: rhodecode/templates/admin/users/user_edit_my_account.html:38
1776 msgid "ADD REPOSITORY"
2533 #: rhodecode/templates/journal/journal.html:41
1777 msgstr ""
2534 msgid "My repos"
1778
2535 msgstr ""
1779 #: rhodecode/templates/admin/users/user_edit_my_account.html:118
2536
1780 #: rhodecode/templates/branches/branches_data.html:7
2537 #: rhodecode/templates/admin/users/user_edit_my_account.html:41
1781 #: rhodecode/templates/shortlog/shortlog_data.html:8
2538 msgid "My pull requests"
1782 #: rhodecode/templates/tags/tags_data.html:7
2539 msgstr ""
1783 msgid "revision"
2540
1784 msgstr ""
2541 #: rhodecode/templates/admin/users/user_edit_my_account.html:45
1785
2542 msgid "Add repo"
1786 #: rhodecode/templates/admin/users/user_edit_my_account.html:157
2543 msgstr ""
2544
2545 #: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:2
2546 msgid "Opened by me"
2547 msgstr ""
2548
2549 #: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:10
2550 #, python-format
2551 msgid "Pull request #%s opened on %s"
2552 msgstr ""
2553
2554 #: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:15
2555 msgid "Confirm to delete this pull request"
2556 msgstr ""
2557
2558 #: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:26
2559 msgid "I participate in"
2560 msgstr ""
2561
2562 #: rhodecode/templates/admin/users/user_edit_my_account_pullrequests.html:33
2563 #: rhodecode/templates/pullrequests/pullrequest_show_all.html:30
2564 #, python-format
2565 msgid "Pull request #%s opened by %s on %s"
2566 msgstr ""
2567
2568 #: rhodecode/templates/admin/users/user_edit_my_account_repos.html:7
2569 #: rhodecode/templates/bookmarks/bookmarks.html:40
2570 #: rhodecode/templates/bookmarks/bookmarks_data.html:9
2571 #: rhodecode/templates/branches/branches.html:55
2572 #: rhodecode/templates/journal/journal.html:60
2573 #: rhodecode/templates/tags/tags.html:40
2574 #: rhodecode/templates/tags/tags_data.html:9
2575 msgid "Revision"
2576 msgstr ""
2577
2578 #: rhodecode/templates/admin/users/user_edit_my_account_repos.html:28
2579 #: rhodecode/templates/journal/journal.html:81
2580 msgid "private"
2581 msgstr ""
2582
2583 #: rhodecode/templates/admin/users/user_edit_my_account_repos.html:31
2584 #: rhodecode/templates/data_table/_dt_elements.html:7
2585 #, python-format
2586 msgid "Confirm to delete this repository: %s"
2587 msgstr ""
2588
2589 #: rhodecode/templates/admin/users/user_edit_my_account_repos.html:38
2590 #: rhodecode/templates/journal/journal.html:94
1787 msgid "No repositories yet"
2591 msgid "No repositories yet"
1788 msgstr ""
2592 msgstr ""
1789
2593
1790 #: rhodecode/templates/admin/users/user_edit_my_account.html:159
2594 #: rhodecode/templates/admin/users/user_edit_my_account_repos.html:40
2595 #: rhodecode/templates/journal/journal.html:96
1791 msgid "create one now"
2596 msgid "create one now"
1792 msgstr ""
2597 msgstr ""
1793
2598
@@ -1795,42 +2600,41 b' msgstr ""'
1795 msgid "Users administration"
2600 msgid "Users administration"
1796 msgstr ""
2601 msgstr ""
1797
2602
2603 #: rhodecode/templates/admin/users/users.html:9
2604 #: rhodecode/templates/base/base.html:223
2605 msgid "users"
2606 msgstr ""
2607
1798 #: rhodecode/templates/admin/users/users.html:23
2608 #: rhodecode/templates/admin/users/users.html:23
1799 msgid "ADD NEW USER"
2609 msgid "ADD NEW USER"
1800 msgstr ""
2610 msgstr ""
1801
2611
1802 #: rhodecode/templates/admin/users/users.html:33
2612 #: rhodecode/templates/admin/users/users.html:77
1803 msgid "username"
2613 msgid "username"
1804 msgstr ""
2614 msgstr ""
1805
2615
1806 #: rhodecode/templates/admin/users/users.html:34
2616 #: rhodecode/templates/admin/users/users.html:80
1807 #: rhodecode/templates/branches/branches_data.html:5
2617 msgid "firstname"
1808 #: rhodecode/templates/tags/tags_data.html:5
2618 msgstr ""
1809 msgid "name"
2619
1810 msgstr ""
2620 #: rhodecode/templates/admin/users/users.html:81
1811
1812 #: rhodecode/templates/admin/users/users.html:35
1813 msgid "lastname"
2621 msgid "lastname"
1814 msgstr ""
2622 msgstr ""
1815
2623
1816 #: rhodecode/templates/admin/users/users.html:36
2624 #: rhodecode/templates/admin/users/users.html:82
1817 msgid "last login"
2625 msgid "last login"
1818 msgstr ""
2626 msgstr ""
1819
2627
1820 #: rhodecode/templates/admin/users/users.html:37
2628 #: rhodecode/templates/admin/users/users.html:84
1821 #: rhodecode/templates/admin/users_groups/users_groups.html:34
2629 #: rhodecode/templates/admin/users_groups/users_groups.html:34
1822 msgid "active"
2630 msgid "active"
1823 msgstr ""
2631 msgstr ""
1824
2632
1825 #: rhodecode/templates/admin/users/users.html:39
2633 #: rhodecode/templates/admin/users/users.html:86
1826 #: rhodecode/templates/base/base.html:305
2634 #: rhodecode/templates/base/base.html:226
1827 msgid "ldap"
2635 msgid "ldap"
1828 msgstr ""
2636 msgstr ""
1829
2637
1830 #: rhodecode/templates/admin/users/users.html:56
1831 msgid "Confirm to delete this user"
1832 msgstr ""
1833
1834 #: rhodecode/templates/admin/users_groups/users_group_add.html:5
2638 #: rhodecode/templates/admin/users_groups/users_group_add.html:5
1835 msgid "Add users group"
2639 msgid "Add users group"
1836 msgstr ""
2640 msgstr ""
@@ -1872,6 +2676,10 b' msgstr ""'
1872 msgid "Add all elements"
2676 msgid "Add all elements"
1873 msgstr ""
2677 msgstr ""
1874
2678
2679 #: rhodecode/templates/admin/users_groups/users_group_edit.html:146
2680 msgid "Group members"
2681 msgstr ""
2682
1875 #: rhodecode/templates/admin/users_groups/users_groups.html:5
2683 #: rhodecode/templates/admin/users_groups/users_groups.html:5
1876 msgid "Users groups administration"
2684 msgid "Users groups administration"
1877 msgstr ""
2685 msgstr ""
@@ -1884,396 +2692,616 b' msgstr ""'
1884 msgid "group name"
2692 msgid "group name"
1885 msgstr ""
2693 msgstr ""
1886
2694
1887 #: rhodecode/templates/base/base.html:32
2695 #: rhodecode/templates/admin/users_groups/users_groups.html:33
2696 #: rhodecode/templates/base/root.html:46
2697 msgid "members"
2698 msgstr ""
2699
2700 #: rhodecode/templates/admin/users_groups/users_groups.html:45
2701 #, python-format
2702 msgid "Confirm to delete this users group: %s"
2703 msgstr ""
2704
2705 #: rhodecode/templates/base/base.html:41
2706 msgid "Submit a bug"
2707 msgstr ""
2708
2709 #: rhodecode/templates/base/base.html:77
2710 msgid "Login to your account"
2711 msgstr ""
2712
2713 #: rhodecode/templates/base/base.html:100
1888 msgid "Forgot password ?"
2714 msgid "Forgot password ?"
1889 msgstr ""
2715 msgstr ""
1890
2716
1891 #: rhodecode/templates/base/base.html:57 rhodecode/templates/base/base.html:338
1892 #: rhodecode/templates/base/base.html:340
1893 #: rhodecode/templates/base/base.html:342
1894 msgid "Home"
1895 msgstr ""
1896
1897 #: rhodecode/templates/base/base.html:61 rhodecode/templates/base/base.html:347
1898 #: rhodecode/templates/base/base.html:349
1899 #: rhodecode/templates/base/base.html:351
1900 #: rhodecode/templates/journal/journal.html:4
1901 #: rhodecode/templates/journal/journal.html:17
1902 #: rhodecode/templates/journal/public_journal.html:4
1903 msgid "Journal"
1904 msgstr ""
1905
1906 #: rhodecode/templates/base/base.html:66
1907 msgid "Login"
1908 msgstr ""
1909
1910 #: rhodecode/templates/base/base.html:68
1911 msgid "Log Out"
1912 msgstr ""
1913
1914 #: rhodecode/templates/base/base.html:107
2717 #: rhodecode/templates/base/base.html:107
1915 msgid "Submit a bug"
2718 msgid "Log In"
1916 msgstr ""
2719 msgstr ""
1917
2720
1918 #: rhodecode/templates/base/base.html:141
2721 #: rhodecode/templates/base/base.html:118
2722 msgid "Inbox"
2723 msgstr ""
2724
2725 #: rhodecode/templates/base/base.html:122
2726 #: rhodecode/templates/base/base.html:300
2727 #: rhodecode/templates/base/base.html:302
2728 #: rhodecode/templates/base/base.html:304
2729 #: rhodecode/templates/bookmarks/bookmarks.html:11
2730 #: rhodecode/templates/branches/branches.html:10
2731 #: rhodecode/templates/changelog/changelog.html:10
2732 #: rhodecode/templates/changeset/changeset.html:10
2733 #: rhodecode/templates/changeset/changeset_range.html:9
2734 #: rhodecode/templates/compare/compare_diff.html:9
2735 #: rhodecode/templates/files/file_diff.html:8
2736 #: rhodecode/templates/files/files.html:8
2737 #: rhodecode/templates/files/files_add.html:15
2738 #: rhodecode/templates/files/files_edit.html:15
2739 #: rhodecode/templates/followers/followers.html:9
2740 #: rhodecode/templates/forks/fork.html:9 rhodecode/templates/forks/forks.html:9
2741 #: rhodecode/templates/pullrequests/pullrequest.html:8
2742 #: rhodecode/templates/pullrequests/pullrequest_show.html:8
2743 #: rhodecode/templates/pullrequests/pullrequest_show_all.html:8
2744 #: rhodecode/templates/settings/repo_settings.html:9
2745 #: rhodecode/templates/shortlog/shortlog.html:10
2746 #: rhodecode/templates/summary/summary.html:8
2747 #: rhodecode/templates/tags/tags.html:11
2748 msgid "Home"
2749 msgstr ""
2750
2751 #: rhodecode/templates/base/base.html:123
2752 #: rhodecode/templates/base/base.html:309
2753 #: rhodecode/templates/base/base.html:311
2754 #: rhodecode/templates/base/base.html:313
2755 #: rhodecode/templates/journal/journal.html:4
2756 #: rhodecode/templates/journal/journal.html:21
2757 #: rhodecode/templates/journal/public_journal.html:4
2758 msgid "Journal"
2759 msgstr ""
2760
2761 #: rhodecode/templates/base/base.html:125
2762 msgid "Log Out"
2763 msgstr ""
2764
2765 #: rhodecode/templates/base/base.html:144
1919 msgid "Switch repository"
2766 msgid "Switch repository"
1920 msgstr ""
2767 msgstr ""
1921
2768
1922 #: rhodecode/templates/base/base.html:143
2769 #: rhodecode/templates/base/base.html:146
1923 msgid "Products"
2770 msgid "Products"
1924 msgstr ""
2771 msgstr ""
1925
2772
1926 #: rhodecode/templates/base/base.html:149
2773 #: rhodecode/templates/base/base.html:152
2774 #: rhodecode/templates/base/base.html:182
1927 msgid "loading..."
2775 msgid "loading..."
1928 msgstr ""
2776 msgstr ""
1929
2777
1930 #: rhodecode/templates/base/base.html:234
2778 #: rhodecode/templates/base/base.html:158
1931 #: rhodecode/templates/base/base.html:236
2779 #: rhodecode/templates/base/base.html:160
1932 #: rhodecode/templates/base/base.html:238
2780 #: rhodecode/templates/base/base.html:162
2781 #: rhodecode/templates/data_table/_dt_elements.html:15
2782 #: rhodecode/templates/data_table/_dt_elements.html:17
2783 #: rhodecode/templates/data_table/_dt_elements.html:19
2784 msgid "Summary"
2785 msgstr ""
2786
2787 #: rhodecode/templates/base/base.html:166
2788 #: rhodecode/templates/base/base.html:168
2789 #: rhodecode/templates/base/base.html:170
2790 #: rhodecode/templates/changelog/changelog.html:15
2791 #: rhodecode/templates/data_table/_dt_elements.html:23
2792 #: rhodecode/templates/data_table/_dt_elements.html:25
2793 #: rhodecode/templates/data_table/_dt_elements.html:27
2794 msgid "Changelog"
2795 msgstr ""
2796
2797 #: rhodecode/templates/base/base.html:175
2798 #: rhodecode/templates/base/base.html:177
2799 #: rhodecode/templates/base/base.html:179
1933 msgid "Switch to"
2800 msgid "Switch to"
1934 msgstr ""
2801 msgstr ""
1935
2802
1936 #: rhodecode/templates/base/base.html:242
2803 #: rhodecode/templates/base/base.html:186
1937 #: rhodecode/templates/branches/branches.html:13
2804 #: rhodecode/templates/base/base.html:188
1938 msgid "branches"
2805 #: rhodecode/templates/base/base.html:190
1939 msgstr ""
2806 #: rhodecode/templates/data_table/_dt_elements.html:31
1940
2807 #: rhodecode/templates/data_table/_dt_elements.html:33
1941 #: rhodecode/templates/base/base.html:249
2808 #: rhodecode/templates/data_table/_dt_elements.html:35
1942 #: rhodecode/templates/branches/branches_data.html:52
2809 msgid "Files"
1943 msgid "There are no branches yet"
2810 msgstr ""
1944 msgstr ""
2811
1945
2812 #: rhodecode/templates/base/base.html:195
1946 #: rhodecode/templates/base/base.html:254
2813 #: rhodecode/templates/base/base.html:199
1947 #: rhodecode/templates/shortlog/shortlog_data.html:10
1948 #: rhodecode/templates/tags/tags.html:14
1949 msgid "tags"
1950 msgstr ""
1951
1952 #: rhodecode/templates/base/base.html:261
1953 #: rhodecode/templates/tags/tags_data.html:32
1954 msgid "There are no tags yet"
1955 msgstr ""
1956
1957 #: rhodecode/templates/base/base.html:277
1958 #: rhodecode/templates/base/base.html:281
1959 #: rhodecode/templates/files/files_annotate.html:40
1960 #: rhodecode/templates/files/files_source.html:11
1961 msgid "Options"
2814 msgid "Options"
1962 msgstr ""
2815 msgstr ""
1963
2816
1964 #: rhodecode/templates/base/base.html:286
2817 #: rhodecode/templates/base/base.html:204
1965 #: rhodecode/templates/base/base.html:288
2818 #: rhodecode/templates/base/base.html:206
1966 #: rhodecode/templates/base/base.html:306
2819 #: rhodecode/templates/base/base.html:227
1967 msgid "settings"
2820 msgid "settings"
1968 msgstr ""
2821 msgstr ""
1969
2822
1970 #: rhodecode/templates/base/base.html:292
2823 #: rhodecode/templates/base/base.html:209
2824 #: rhodecode/templates/data_table/_dt_elements.html:80
2825 #: rhodecode/templates/forks/fork.html:13
2826 msgid "fork"
2827 msgstr ""
2828
2829 #: rhodecode/templates/base/base.html:211
2830 #: rhodecode/templates/changelog/changelog.html:40
2831 msgid "Open new pull request"
2832 msgstr ""
2833
2834 #: rhodecode/templates/base/base.html:213
1971 msgid "search"
2835 msgid "search"
1972 msgstr ""
2836 msgstr ""
1973
2837
1974 #: rhodecode/templates/base/base.html:299
2838 #: rhodecode/templates/base/base.html:222
1975 msgid "journal"
1976 msgstr ""
1977
1978 #: rhodecode/templates/base/base.html:301
1979 msgid "repositories groups"
2839 msgid "repositories groups"
1980 msgstr ""
2840 msgstr ""
1981
2841
1982 #: rhodecode/templates/base/base.html:302
2842 #: rhodecode/templates/base/base.html:224
1983 msgid "users"
1984 msgstr ""
1985
1986 #: rhodecode/templates/base/base.html:303
1987 msgid "users groups"
2843 msgid "users groups"
1988 msgstr ""
2844 msgstr ""
1989
2845
1990 #: rhodecode/templates/base/base.html:304
2846 #: rhodecode/templates/base/base.html:225
1991 msgid "permissions"
2847 msgid "permissions"
1992 msgstr ""
2848 msgstr ""
1993
2849
1994 #: rhodecode/templates/base/base.html:317
2850 #: rhodecode/templates/base/base.html:238
1995 #: rhodecode/templates/base/base.html:319
2851 #: rhodecode/templates/base/base.html:240
1996 #: rhodecode/templates/followers/followers.html:5
1997 msgid "Followers"
2852 msgid "Followers"
1998 msgstr ""
2853 msgstr ""
1999
2854
2000 #: rhodecode/templates/base/base.html:325
2855 #: rhodecode/templates/base/base.html:246
2856 #: rhodecode/templates/base/base.html:248
2857 msgid "Forks"
2858 msgstr ""
2859
2001 #: rhodecode/templates/base/base.html:327
2860 #: rhodecode/templates/base/base.html:327
2002 #: rhodecode/templates/forks/forks.html:5
2861 #: rhodecode/templates/base/base.html:329
2003 msgid "Forks"
2862 #: rhodecode/templates/base/base.html:331
2004 msgstr ""
2863 #: rhodecode/templates/search/search.html:52
2005
2006 #: rhodecode/templates/base/base.html:356
2007 #: rhodecode/templates/base/base.html:358
2008 #: rhodecode/templates/base/base.html:360
2009 #: rhodecode/templates/search/search.html:4
2010 #: rhodecode/templates/search/search.html:24
2011 #: rhodecode/templates/search/search.html:46
2012 msgid "Search"
2864 msgid "Search"
2013 msgstr ""
2865 msgstr ""
2014
2866
2015 #: rhodecode/templates/base/root.html:57
2867 #: rhodecode/templates/base/root.html:42
2016 #: rhodecode/templates/journal/journal.html:48
2868 msgid "add another comment"
2017 #: rhodecode/templates/summary/summary.html:36
2869 msgstr ""
2870
2871 #: rhodecode/templates/base/root.html:43
2872 #: rhodecode/templates/journal/journal.html:120
2873 #: rhodecode/templates/summary/summary.html:57
2018 msgid "Stop following this repository"
2874 msgid "Stop following this repository"
2019 msgstr ""
2875 msgstr ""
2020
2876
2021 #: rhodecode/templates/base/root.html:66
2877 #: rhodecode/templates/base/root.html:44
2022 #: rhodecode/templates/summary/summary.html:40
2878 #: rhodecode/templates/summary/summary.html:61
2023 msgid "Start following this repository"
2879 msgid "Start following this repository"
2024 msgstr ""
2880 msgstr ""
2025
2881
2026 #: rhodecode/templates/branches/branches_data.html:4
2882 #: rhodecode/templates/base/root.html:45
2027 #: rhodecode/templates/tags/tags_data.html:4
2883 msgid "Group"
2028 msgid "date"
2884 msgstr ""
2885
2886 #: rhodecode/templates/base/root.html:47
2887 msgid "search truncated"
2888 msgstr ""
2889
2890 #: rhodecode/templates/base/root.html:48
2891 msgid "no matching files"
2892 msgstr ""
2893
2894 #: rhodecode/templates/bookmarks/bookmarks.html:5
2895 #, python-format
2896 msgid "%s Bookmarks"
2897 msgstr ""
2898
2899 #: rhodecode/templates/bookmarks/bookmarks.html:39
2900 #: rhodecode/templates/bookmarks/bookmarks_data.html:8
2901 #: rhodecode/templates/branches/branches.html:54
2902 #: rhodecode/templates/tags/tags.html:39
2903 #: rhodecode/templates/tags/tags_data.html:8
2904 msgid "Author"
2905 msgstr ""
2906
2907 #: rhodecode/templates/branches/branches.html:5
2908 #, python-format
2909 msgid "%s Branches"
2910 msgstr ""
2911
2912 #: rhodecode/templates/branches/branches.html:29
2913 msgid "Compare branches"
2914 msgstr ""
2915
2916 #: rhodecode/templates/branches/branches.html:57
2917 #: rhodecode/templates/compare/compare_diff.html:5
2918 #: rhodecode/templates/compare/compare_diff.html:13
2919 msgid "Compare"
2029 msgstr ""
2920 msgstr ""
2030
2921
2031 #: rhodecode/templates/branches/branches_data.html:6
2922 #: rhodecode/templates/branches/branches_data.html:6
2032 #: rhodecode/templates/shortlog/shortlog_data.html:7
2923 msgid "name"
2033 #: rhodecode/templates/tags/tags_data.html:6
2924 msgstr ""
2034 msgid "author"
2925
2926 #: rhodecode/templates/branches/branches_data.html:7
2927 msgid "date"
2035 msgstr ""
2928 msgstr ""
2036
2929
2037 #: rhodecode/templates/branches/branches_data.html:8
2930 #: rhodecode/templates/branches/branches_data.html:8
2038 #: rhodecode/templates/shortlog/shortlog_data.html:11
2931 #: rhodecode/templates/shortlog/shortlog_data.html:8
2039 #: rhodecode/templates/tags/tags_data.html:8
2932 msgid "author"
2040 msgid "links"
2933 msgstr ""
2041 msgstr ""
2934
2042
2935 #: rhodecode/templates/branches/branches_data.html:9
2043 #: rhodecode/templates/branches/branches_data.html:23
2936 #: rhodecode/templates/shortlog/shortlog_data.html:5
2044 #: rhodecode/templates/branches/branches_data.html:43
2937 msgid "revision"
2045 #: rhodecode/templates/shortlog/shortlog_data.html:39
2938 msgstr ""
2046 #: rhodecode/templates/tags/tags_data.html:24
2939
2047 msgid "changeset"
2940 #: rhodecode/templates/branches/branches_data.html:10
2048 msgstr ""
2941 msgid "compare"
2049
2942 msgstr ""
2050 #: rhodecode/templates/branches/branches_data.html:25
2943
2051 #: rhodecode/templates/branches/branches_data.html:45
2944 #: rhodecode/templates/changelog/changelog.html:6
2052 #: rhodecode/templates/files/files.html:12
2945 #, python-format
2053 #: rhodecode/templates/shortlog/shortlog_data.html:41
2946 msgid "%s Changelog"
2054 #: rhodecode/templates/summary/summary.html:233
2947 msgstr ""
2055 #: rhodecode/templates/tags/tags_data.html:26
2948
2056 msgid "files"
2949 #: rhodecode/templates/changelog/changelog.html:15
2057 msgstr ""
2950 #, python-format
2058
2951 msgid "showing %d out of %d revision"
2059 #: rhodecode/templates/changelog/changelog.html:14
2952 msgid_plural "showing %d out of %d revisions"
2060 msgid "showing "
2953 msgstr[0] ""
2061 msgstr ""
2954 msgstr[1] ""
2062
2955
2063 #: rhodecode/templates/changelog/changelog.html:14
2956 #: rhodecode/templates/changelog/changelog.html:37
2064 msgid "out of"
2957 #: rhodecode/templates/forks/forks_data.html:19
2958 #, python-format
2959 msgid "compare fork with %s"
2065 msgstr ""
2960 msgstr ""
2066
2961
2067 #: rhodecode/templates/changelog/changelog.html:37
2962 #: rhodecode/templates/changelog/changelog.html:37
2963 #: rhodecode/templates/forks/forks_data.html:21
2964 msgid "Compare fork"
2965 msgstr ""
2966
2967 #: rhodecode/templates/changelog/changelog.html:46
2068 msgid "Show"
2968 msgid "Show"
2069 msgstr ""
2969 msgstr ""
2070
2970
2071 #: rhodecode/templates/changelog/changelog.html:50
2072 #: rhodecode/templates/changeset/changeset.html:42
2073 #: rhodecode/templates/summary/summary.html:609
2074 msgid "commit"
2075 msgstr ""
2076
2077 #: rhodecode/templates/changelog/changelog.html:63
2078 msgid "Affected number of files, click to show more details"
2079 msgstr ""
2080
2081 #: rhodecode/templates/changelog/changelog.html:67
2082 #: rhodecode/templates/changeset/changeset.html:66
2083 msgid "merge"
2084 msgstr ""
2085
2086 #: rhodecode/templates/changelog/changelog.html:72
2971 #: rhodecode/templates/changelog/changelog.html:72
2087 #: rhodecode/templates/changeset/changeset.html:72
2972 #: rhodecode/templates/summary/summary.html:364
2973 msgid "show more"
2974 msgstr ""
2975
2976 #: rhodecode/templates/changelog/changelog.html:76
2977 msgid "Affected number of files, click to show more details"
2978 msgstr ""
2979
2980 #: rhodecode/templates/changelog/changelog.html:89
2981 #: rhodecode/templates/changeset/changeset.html:38
2982 #: rhodecode/templates/changeset/changeset_file_comment.html:20
2983 #: rhodecode/templates/changeset/changeset_range.html:46
2984 msgid "Changeset status"
2985 msgstr ""
2986
2987 #: rhodecode/templates/changelog/changelog.html:92
2988 msgid "Click to open associated pull request"
2989 msgstr ""
2990
2991 #: rhodecode/templates/changelog/changelog.html:102
2992 #: rhodecode/templates/changeset/changeset.html:78
2088 msgid "Parent"
2993 msgid "Parent"
2089 msgstr ""
2994 msgstr ""
2090
2995
2091 #: rhodecode/templates/changelog/changelog.html:77
2996 #: rhodecode/templates/changelog/changelog.html:108
2092 #: rhodecode/templates/changeset/changeset.html:77
2997 #: rhodecode/templates/changeset/changeset.html:84
2093 msgid "No parents"
2998 msgid "No parents"
2094 msgstr ""
2999 msgstr ""
2095
3000
2096 #: rhodecode/templates/changelog/changelog.html:82
3001 #: rhodecode/templates/changelog/changelog.html:113
2097 #: rhodecode/templates/changeset/changeset.html:80
3002 #: rhodecode/templates/changeset/changeset.html:88
3003 msgid "merge"
3004 msgstr ""
3005
3006 #: rhodecode/templates/changelog/changelog.html:116
3007 #: rhodecode/templates/changeset/changeset.html:91
2098 #: rhodecode/templates/files/files.html:29
3008 #: rhodecode/templates/files/files.html:29
2099 #: rhodecode/templates/files/files_annotate.html:25
3009 #: rhodecode/templates/files/files_add.html:33
2100 #: rhodecode/templates/files/files_edit.html:33
3010 #: rhodecode/templates/files/files_edit.html:33
2101 #: rhodecode/templates/shortlog/shortlog_data.html:9
3011 #: rhodecode/templates/shortlog/shortlog_data.html:9
2102 msgid "branch"
3012 msgid "branch"
2103 msgstr ""
3013 msgstr ""
2104
3014
2105 #: rhodecode/templates/changelog/changelog.html:86
3015 #: rhodecode/templates/changelog/changelog.html:122
2106 #: rhodecode/templates/changeset/changeset.html:83
3016 msgid "bookmark"
3017 msgstr ""
3018
3019 #: rhodecode/templates/changelog/changelog.html:128
3020 #: rhodecode/templates/changeset/changeset.html:96
2107 msgid "tag"
3021 msgid "tag"
2108 msgstr ""
3022 msgstr ""
2109
3023
2110 #: rhodecode/templates/changelog/changelog.html:122
3024 #: rhodecode/templates/changelog/changelog.html:164
2111 msgid "Show selected changes __S -> __E"
3025 msgid "Show selected changes __S -> __E"
2112 msgstr ""
3026 msgstr ""
2113
3027
2114 #: rhodecode/templates/changelog/changelog.html:172
3028 #: rhodecode/templates/changelog/changelog.html:255
2115 #: rhodecode/templates/shortlog/shortlog_data.html:61
2116 msgid "There are no changes yet"
3029 msgid "There are no changes yet"
2117 msgstr ""
3030 msgstr ""
2118
3031
2119 #: rhodecode/templates/changelog/changelog_details.html:2
2120 #: rhodecode/templates/changeset/changeset.html:55
2121 msgid "removed"
2122 msgstr ""
2123
2124 #: rhodecode/templates/changelog/changelog_details.html:3
2125 #: rhodecode/templates/changeset/changeset.html:56
2126 msgid "changed"
2127 msgstr ""
2128
2129 #: rhodecode/templates/changelog/changelog_details.html:4
3032 #: rhodecode/templates/changelog/changelog_details.html:4
2130 #: rhodecode/templates/changeset/changeset.html:57
3033 #: rhodecode/templates/changeset/changeset.html:66
2131 msgid "added"
3034 msgid "removed"
3035 msgstr ""
3036
3037 #: rhodecode/templates/changelog/changelog_details.html:5
3038 #: rhodecode/templates/changeset/changeset.html:67
3039 msgid "changed"
2132 msgstr ""
3040 msgstr ""
2133
3041
2134 #: rhodecode/templates/changelog/changelog_details.html:6
3042 #: rhodecode/templates/changelog/changelog_details.html:6
2135 #: rhodecode/templates/changelog/changelog_details.html:7
3043 #: rhodecode/templates/changeset/changeset.html:68
3044 msgid "added"
3045 msgstr ""
3046
2136 #: rhodecode/templates/changelog/changelog_details.html:8
3047 #: rhodecode/templates/changelog/changelog_details.html:8
2137 #: rhodecode/templates/changeset/changeset.html:59
3048 #: rhodecode/templates/changelog/changelog_details.html:9
2138 #: rhodecode/templates/changeset/changeset.html:60
3049 #: rhodecode/templates/changelog/changelog_details.html:10
2139 #: rhodecode/templates/changeset/changeset.html:61
3050 #: rhodecode/templates/changeset/changeset.html:70
3051 #: rhodecode/templates/changeset/changeset.html:71
3052 #: rhodecode/templates/changeset/changeset.html:72
2140 #, python-format
3053 #, python-format
2141 msgid "affected %s files"
3054 msgid "affected %s files"
2142 msgstr ""
3055 msgstr ""
2143
3056
2144 #: rhodecode/templates/changeset/changeset.html:6
3057 #: rhodecode/templates/changeset/changeset.html:6
3058 #, python-format
3059 msgid "%s Changeset"
3060 msgstr ""
3061
2145 #: rhodecode/templates/changeset/changeset.html:14
3062 #: rhodecode/templates/changeset/changeset.html:14
2146 #: rhodecode/templates/changeset/changeset.html:31
2147 msgid "Changeset"
3063 msgid "Changeset"
2148 msgstr ""
3064 msgstr ""
2149
3065
2150 #: rhodecode/templates/changeset/changeset.html:32
3066 #: rhodecode/templates/changeset/changeset.html:43
2151 #: rhodecode/templates/changeset/changeset.html:121
3067 #: rhodecode/templates/changeset/diff_block.html:20
2152 #: rhodecode/templates/changeset/changeset_range.html:78
2153 #: rhodecode/templates/files/file_diff.html:32
2154 #: rhodecode/templates/files/file_diff.html:42
2155 msgid "raw diff"
3068 msgid "raw diff"
2156 msgstr ""
3069 msgstr ""
2157
3070
2158 #: rhodecode/templates/changeset/changeset.html:34
3071 #: rhodecode/templates/changeset/changeset.html:44
2159 #: rhodecode/templates/changeset/changeset.html:123
3072 #: rhodecode/templates/changeset/diff_block.html:21
2160 #: rhodecode/templates/changeset/changeset_range.html:80
2161 #: rhodecode/templates/files/file_diff.html:34
2162 msgid "download diff"
3073 msgid "download diff"
2163 msgstr ""
3074 msgstr ""
2164
3075
2165 #: rhodecode/templates/changeset/changeset.html:90
3076 #: rhodecode/templates/changeset/changeset.html:48
3077 #: rhodecode/templates/changeset/changeset_file_comment.html:82
2166 #, python-format
3078 #, python-format
2167 msgid "%s files affected with %s additions and %s deletions."
3079 msgid "%d comment"
2168 msgstr ""
3080 msgid_plural "%d comments"
2169
3081 msgstr[0] ""
2170 #: rhodecode/templates/changeset/changeset.html:101
3082 msgstr[1] ""
2171 msgid "Changeset was too big and was cut off..."
3083
3084 #: rhodecode/templates/changeset/changeset.html:48
3085 #: rhodecode/templates/changeset/changeset_file_comment.html:82
3086 #, python-format
3087 msgid "(%d inline)"
3088 msgid_plural "(%d inline)"
3089 msgstr[0] ""
3090 msgstr[1] ""
3091
3092 #: rhodecode/templates/changeset/changeset.html:103
3093 #, python-format
3094 msgid "%s files affected with %s insertions and %s deletions:"
2172 msgstr ""
3095 msgstr ""
2173
3096
2174 #: rhodecode/templates/changeset/changeset.html:119
3097 #: rhodecode/templates/changeset/changeset.html:119
2175 #: rhodecode/templates/changeset/changeset_range.html:76
3098 msgid "Changeset was too big and was cut off..."
2176 #: rhodecode/templates/files/file_diff.html:30
3099 msgstr ""
3100
3101 #: rhodecode/templates/changeset/changeset_file_comment.html:42
3102 msgid "Submitting..."
3103 msgstr ""
3104
3105 #: rhodecode/templates/changeset/changeset_file_comment.html:45
3106 msgid "Commenting on line {1}."
3107 msgstr ""
3108
3109 #: rhodecode/templates/changeset/changeset_file_comment.html:46
3110 #: rhodecode/templates/changeset/changeset_file_comment.html:121
3111 #, python-format
3112 msgid "Comments parsed using %s syntax with %s support."
3113 msgstr ""
3114
3115 #: rhodecode/templates/changeset/changeset_file_comment.html:48
3116 #: rhodecode/templates/changeset/changeset_file_comment.html:123
3117 msgid "Use @username inside this text to send notification to this RhodeCode user"
3118 msgstr ""
3119
3120 #: rhodecode/templates/changeset/changeset_file_comment.html:59
3121 #: rhodecode/templates/changeset/changeset_file_comment.html:138
3122 msgid "Comment"
3123 msgstr ""
3124
3125 #: rhodecode/templates/changeset/changeset_file_comment.html:60
3126 #: rhodecode/templates/changeset/changeset_file_comment.html:71
3127 msgid "Hide"
3128 msgstr ""
3129
3130 #: rhodecode/templates/changeset/changeset_file_comment.html:67
3131 msgid "You need to be logged in to comment."
3132 msgstr ""
3133
3134 #: rhodecode/templates/changeset/changeset_file_comment.html:67
3135 msgid "Login now"
3136 msgstr ""
3137
3138 #: rhodecode/templates/changeset/changeset_file_comment.html:118
3139 msgid "Leave a comment"
3140 msgstr ""
3141
3142 #: rhodecode/templates/changeset/changeset_file_comment.html:124
3143 msgid "Check this to change current status of code-review for this changeset"
3144 msgstr ""
3145
3146 #: rhodecode/templates/changeset/changeset_file_comment.html:124
3147 msgid "change status"
3148 msgstr ""
3149
3150 #: rhodecode/templates/changeset/changeset_file_comment.html:140
3151 msgid "Comment and close"
3152 msgstr ""
3153
3154 #: rhodecode/templates/changeset/changeset_range.html:5
3155 #, python-format
3156 msgid "%s Changesets"
3157 msgstr ""
3158
3159 #: rhodecode/templates/changeset/changeset_range.html:29
3160 #: rhodecode/templates/compare/compare_diff.html:29
3161 msgid "Compare View"
3162 msgstr ""
3163
3164 #: rhodecode/templates/changeset/changeset_range.html:54
3165 #: rhodecode/templates/compare/compare_diff.html:41
3166 #: rhodecode/templates/pullrequests/pullrequest_show.html:69
3167 msgid "Files affected"
3168 msgstr ""
3169
3170 #: rhodecode/templates/changeset/diff_block.html:19
2177 msgid "diff"
3171 msgid "diff"
2178 msgstr ""
3172 msgstr ""
2179
3173
2180 #: rhodecode/templates/changeset/changeset.html:132
3174 #: rhodecode/templates/changeset/diff_block.html:27
2181 #: rhodecode/templates/changeset/changeset_range.html:89
3175 msgid "show inline comments"
2182 msgid "No changes in this file"
3176 msgstr ""
2183 msgstr ""
3177
2184
3178 #: rhodecode/templates/compare/compare_cs.html:5
2185 #: rhodecode/templates/changeset/changeset_range.html:30
3179 msgid "No changesets"
2186 msgid "Compare View"
3180 msgstr ""
2187 msgstr ""
3181
2188
3182 #: rhodecode/templates/compare/compare_diff.html:37
2189 #: rhodecode/templates/changeset/changeset_range.html:52
3183 msgid "Outgoing changesets"
2190 msgid "Files affected"
3184 msgstr ""
2191 msgstr ""
3185
2192
3186 #: rhodecode/templates/data_table/_dt_elements.html:39
2193 #: rhodecode/templates/errors/error_document.html:44
3187 #: rhodecode/templates/data_table/_dt_elements.html:41
3188 #: rhodecode/templates/data_table/_dt_elements.html:43
3189 msgid "Fork"
3190 msgstr ""
3191
3192 #: rhodecode/templates/data_table/_dt_elements.html:60
3193 #: rhodecode/templates/journal/journal.html:126
3194 #: rhodecode/templates/summary/summary.html:68
3195 msgid "Mercurial repository"
3196 msgstr ""
3197
3198 #: rhodecode/templates/data_table/_dt_elements.html:62
3199 #: rhodecode/templates/journal/journal.html:128
3200 #: rhodecode/templates/summary/summary.html:71
3201 msgid "Git repository"
3202 msgstr ""
3203
3204 #: rhodecode/templates/data_table/_dt_elements.html:69
3205 #: rhodecode/templates/journal/journal.html:134
3206 #: rhodecode/templates/summary/summary.html:78
3207 msgid "public repository"
3208 msgstr ""
3209
3210 #: rhodecode/templates/data_table/_dt_elements.html:80
3211 #: rhodecode/templates/summary/summary.html:87
3212 #: rhodecode/templates/summary/summary.html:88
3213 msgid "Fork of"
3214 msgstr ""
3215
3216 #: rhodecode/templates/data_table/_dt_elements.html:92
3217 msgid "No changesets yet"
3218 msgstr ""
3219
3220 #: rhodecode/templates/data_table/_dt_elements.html:104
3221 #, python-format
3222 msgid "Confirm to delete this user: %s"
3223 msgstr ""
3224
3225 #: rhodecode/templates/email_templates/main.html:8
3226 msgid "This is an notification from RhodeCode."
3227 msgstr ""
3228
3229 #: rhodecode/templates/errors/error_document.html:46
2194 #, python-format
3230 #, python-format
2195 msgid "You will be redirected to %s in %s seconds"
3231 msgid "You will be redirected to %s in %s seconds"
2196 msgstr ""
3232 msgstr ""
2197
3233
2198 #: rhodecode/templates/files/file_diff.html:4
3234 #: rhodecode/templates/files/file_diff.html:4
3235 #, python-format
3236 msgid "%s File diff"
3237 msgstr ""
3238
2199 #: rhodecode/templates/files/file_diff.html:12
3239 #: rhodecode/templates/files/file_diff.html:12
2200 msgid "File diff"
3240 msgid "File diff"
2201 msgstr ""
3241 msgstr ""
2202
3242
2203 #: rhodecode/templates/files/file_diff.html:42
3243 #: rhodecode/templates/files/files.html:4
2204 msgid "Diff is to big to display"
3244 #: rhodecode/templates/files/files.html:72
2205 msgstr ""
3245 #, python-format
2206
3246 msgid "%s files"
2207 #: rhodecode/templates/files/files.html:37
3247 msgstr ""
2208 #: rhodecode/templates/files/files_annotate.html:31
3248
3249 #: rhodecode/templates/files/files.html:12
3250 #: rhodecode/templates/summary/summary.html:340
3251 msgid "files"
3252 msgstr ""
3253
3254 #: rhodecode/templates/files/files_add.html:4
3255 #: rhodecode/templates/files/files_edit.html:4
3256 #, python-format
3257 msgid "%s Edit file"
3258 msgstr ""
3259
3260 #: rhodecode/templates/files/files_add.html:19
3261 msgid "add file"
3262 msgstr ""
3263
3264 #: rhodecode/templates/files/files_add.html:40
3265 msgid "Add new file"
3266 msgstr ""
3267
3268 #: rhodecode/templates/files/files_add.html:45
3269 msgid "File Name"
3270 msgstr ""
3271
3272 #: rhodecode/templates/files/files_add.html:49
3273 #: rhodecode/templates/files/files_add.html:58
3274 msgid "or"
3275 msgstr ""
3276
3277 #: rhodecode/templates/files/files_add.html:49
3278 #: rhodecode/templates/files/files_add.html:54
3279 msgid "Upload file"
3280 msgstr ""
3281
3282 #: rhodecode/templates/files/files_add.html:58
3283 msgid "Create new file"
3284 msgstr ""
3285
3286 #: rhodecode/templates/files/files_add.html:63
2209 #: rhodecode/templates/files/files_edit.html:39
3287 #: rhodecode/templates/files/files_edit.html:39
3288 #: rhodecode/templates/files/files_ypjax.html:3
2210 msgid "Location"
3289 msgid "Location"
2211 msgstr ""
3290 msgstr ""
2212
3291
2213 #: rhodecode/templates/files/files.html:46
3292 #: rhodecode/templates/files/files_add.html:67
2214 msgid "Go back"
3293 msgid "use / to separate directories"
2215 msgstr ""
3294 msgstr ""
2216
3295
2217 #: rhodecode/templates/files/files.html:47
3296 #: rhodecode/templates/files/files_add.html:77
2218 msgid "No files at given path"
3297 #: rhodecode/templates/files/files_edit.html:63
2219 msgstr ""
3298 #: rhodecode/templates/shortlog/shortlog_data.html:6
2220
3299 msgid "commit message"
2221 #: rhodecode/templates/files/files_annotate.html:4
3300 msgstr ""
2222 msgid "File annotate"
3301
2223 msgstr ""
3302 #: rhodecode/templates/files/files_add.html:81
2224
3303 #: rhodecode/templates/files/files_edit.html:67
2225 #: rhodecode/templates/files/files_annotate.html:12
3304 msgid "Commit changes"
2226 msgid "annotate"
2227 msgstr ""
2228
2229 #: rhodecode/templates/files/files_annotate.html:33
2230 #: rhodecode/templates/files/files_browser.html:160
2231 #: rhodecode/templates/files/files_source.html:2
2232 msgid "Revision"
2233 msgstr ""
2234
2235 #: rhodecode/templates/files/files_annotate.html:36
2236 #: rhodecode/templates/files/files_browser.html:158
2237 #: rhodecode/templates/files/files_source.html:7
2238 msgid "Size"
2239 msgstr ""
2240
2241 #: rhodecode/templates/files/files_annotate.html:38
2242 #: rhodecode/templates/files/files_browser.html:159
2243 #: rhodecode/templates/files/files_source.html:9
2244 msgid "Mimetype"
2245 msgstr ""
2246
2247 #: rhodecode/templates/files/files_annotate.html:41
2248 msgid "show source"
2249 msgstr ""
2250
2251 #: rhodecode/templates/files/files_annotate.html:43
2252 #: rhodecode/templates/files/files_annotate.html:78
2253 #: rhodecode/templates/files/files_source.html:14
2254 #: rhodecode/templates/files/files_source.html:51
2255 msgid "show as raw"
2256 msgstr ""
2257
2258 #: rhodecode/templates/files/files_annotate.html:45
2259 #: rhodecode/templates/files/files_source.html:16
2260 msgid "download as raw"
2261 msgstr ""
2262
2263 #: rhodecode/templates/files/files_annotate.html:54
2264 #: rhodecode/templates/files/files_source.html:25
2265 msgid "History"
2266 msgstr ""
2267
2268 #: rhodecode/templates/files/files_annotate.html:73
2269 #: rhodecode/templates/files/files_source.html:46
2270 #, python-format
2271 msgid "Binary file (%s)"
2272 msgstr ""
2273
2274 #: rhodecode/templates/files/files_annotate.html:78
2275 #: rhodecode/templates/files/files_source.html:51
2276 msgid "File is too big to display"
2277 msgstr ""
3305 msgstr ""
2278
3306
2279 #: rhodecode/templates/files/files_browser.html:13
3307 #: rhodecode/templates/files/files_browser.html:13
@@ -2296,57 +3324,161 b' msgstr ""'
2296 msgid "search file list"
3324 msgid "search file list"
2297 msgstr ""
3325 msgstr ""
2298
3326
2299 #: rhodecode/templates/files/files_browser.html:32
3327 #: rhodecode/templates/files/files_browser.html:31
3328 #: rhodecode/templates/shortlog/shortlog_data.html:65
3329 msgid "add new file"
3330 msgstr ""
3331
3332 #: rhodecode/templates/files/files_browser.html:35
2300 msgid "Loading file list..."
3333 msgid "Loading file list..."
2301 msgstr ""
3334 msgstr ""
2302
3335
2303 #: rhodecode/templates/files/files_browser.html:111
3336 #: rhodecode/templates/files/files_browser.html:48
2304 msgid "search truncated"
3337 msgid "Size"
2305 msgstr ""
3338 msgstr ""
2306
3339
2307 #: rhodecode/templates/files/files_browser.html:122
3340 #: rhodecode/templates/files/files_browser.html:49
2308 msgid "no matching files"
3341 msgid "Mimetype"
2309 msgstr ""
3342 msgstr ""
2310
3343
2311 #: rhodecode/templates/files/files_browser.html:161
3344 #: rhodecode/templates/files/files_browser.html:50
3345 msgid "Last Revision"
3346 msgstr ""
3347
3348 #: rhodecode/templates/files/files_browser.html:51
2312 msgid "Last modified"
3349 msgid "Last modified"
2313 msgstr ""
3350 msgstr ""
2314
3351
2315 #: rhodecode/templates/files/files_browser.html:162
3352 #: rhodecode/templates/files/files_browser.html:52
2316 msgid "Last commiter"
3353 msgid "Last commiter"
2317 msgstr ""
3354 msgstr ""
2318
3355
2319 #: rhodecode/templates/files/files_edit.html:4
2320 msgid "Edit file"
2321 msgstr ""
2322
2323 #: rhodecode/templates/files/files_edit.html:19
3356 #: rhodecode/templates/files/files_edit.html:19
2324 msgid "edit file"
3357 msgid "edit file"
2325 msgstr ""
3358 msgstr ""
2326
3359
2327 #: rhodecode/templates/files/files_edit.html:45
3360 #: rhodecode/templates/files/files_edit.html:49
2328 #: rhodecode/templates/shortlog/shortlog_data.html:5
3361 #: rhodecode/templates/files/files_source.html:38
2329 msgid "commit message"
3362 msgid "show annotation"
3363 msgstr ""
3364
3365 #: rhodecode/templates/files/files_edit.html:50
3366 #: rhodecode/templates/files/files_source.html:40
3367 #: rhodecode/templates/files/files_source.html:68
3368 msgid "show as raw"
2330 msgstr ""
3369 msgstr ""
2331
3370
2332 #: rhodecode/templates/files/files_edit.html:51
3371 #: rhodecode/templates/files/files_edit.html:51
2333 msgid "Commit changes"
3372 #: rhodecode/templates/files/files_source.html:41
2334 msgstr ""
3373 msgid "download as raw"
2335
3374 msgstr ""
2336 #: rhodecode/templates/files/files_source.html:12
3375
2337 msgid "show annotation"
3376 #: rhodecode/templates/files/files_edit.html:54
2338 msgstr ""
3377 msgid "source"
2339
3378 msgstr ""
2340 #: rhodecode/templates/files/files_source.html:153
3379
3380 #: rhodecode/templates/files/files_edit.html:59
3381 msgid "Editing file"
3382 msgstr ""
3383
3384 #: rhodecode/templates/files/files_source.html:2
3385 msgid "History"
3386 msgstr ""
3387
3388 #: rhodecode/templates/files/files_source.html:9
3389 msgid "diff to revision"
3390 msgstr ""
3391
3392 #: rhodecode/templates/files/files_source.html:10
3393 #, fuzzy
3394 msgid "show at revision"
3395 msgstr ""
3396
3397 #: rhodecode/templates/files/files_source.html:14
3398 #, fuzzy, python-format
3399 msgid "%s author"
3400 msgid_plural "%s authors"
3401 msgstr[0] ""
3402 msgstr[1] ""
3403
3404 #: rhodecode/templates/files/files_source.html:36
3405 msgid "show source"
3406 msgstr ""
3407
3408 #: rhodecode/templates/files/files_source.html:59
3409 #, python-format
3410 msgid "Binary file (%s)"
3411 msgstr ""
3412
3413 #: rhodecode/templates/files/files_source.html:68
3414 msgid "File is too big to display"
3415 msgstr ""
3416
3417 #: rhodecode/templates/files/files_source.html:124
2341 msgid "Selection link"
3418 msgid "Selection link"
2342 msgstr ""
3419 msgstr ""
2343
3420
3421 #: rhodecode/templates/files/files_ypjax.html:5
3422 msgid "annotation"
3423 msgstr ""
3424
3425 #: rhodecode/templates/files/files_ypjax.html:15
3426 msgid "Go back"
3427 msgstr ""
3428
3429 #: rhodecode/templates/files/files_ypjax.html:16
3430 msgid "No files at given path"
3431 msgstr ""
3432
3433 #: rhodecode/templates/followers/followers.html:5
3434 #, python-format
3435 msgid "%s Followers"
3436 msgstr ""
3437
2344 #: rhodecode/templates/followers/followers.html:13
3438 #: rhodecode/templates/followers/followers.html:13
2345 msgid "followers"
3439 msgid "followers"
2346 msgstr ""
3440 msgstr ""
2347
3441
2348 #: rhodecode/templates/followers/followers_data.html:12
3442 #: rhodecode/templates/followers/followers_data.html:12
2349 msgid "Started following"
3443 msgid "Started following -"
3444 msgstr ""
3445
3446 #: rhodecode/templates/forks/fork.html:5
3447 #, python-format
3448 msgid "%s Fork"
3449 msgstr ""
3450
3451 #: rhodecode/templates/forks/fork.html:31
3452 msgid "Fork name"
3453 msgstr ""
3454
3455 #: rhodecode/templates/forks/fork.html:68
3456 msgid "Private"
3457 msgstr ""
3458
3459 #: rhodecode/templates/forks/fork.html:77
3460 msgid "Copy permissions"
3461 msgstr ""
3462
3463 #: rhodecode/templates/forks/fork.html:81
3464 msgid "Copy permissions from forked repository"
3465 msgstr ""
3466
3467 #: rhodecode/templates/forks/fork.html:86
3468 msgid "Update after clone"
3469 msgstr ""
3470
3471 #: rhodecode/templates/forks/fork.html:90
3472 msgid "Checkout source after making a clone"
3473 msgstr ""
3474
3475 #: rhodecode/templates/forks/fork.html:94
3476 msgid "fork this repository"
3477 msgstr ""
3478
3479 #: rhodecode/templates/forks/forks.html:5
3480 #, python-format
3481 msgid "%s Forks"
2350 msgstr ""
3482 msgstr ""
2351
3483
2352 #: rhodecode/templates/forks/forks.html:13
3484 #: rhodecode/templates/forks/forks.html:13
@@ -2357,184 +3489,395 b' msgstr ""'
2357 msgid "forked"
3489 msgid "forked"
2358 msgstr ""
3490 msgstr ""
2359
3491
2360 #: rhodecode/templates/forks/forks_data.html:34
3492 #: rhodecode/templates/forks/forks_data.html:38
2361 msgid "There are no forks yet"
3493 msgid "There are no forks yet"
2362 msgstr ""
3494 msgstr ""
2363
3495
2364 #: rhodecode/templates/journal/journal.html:34
3496 #: rhodecode/templates/journal/journal.html:13
2365 msgid "Following"
3497 msgid "ATOM journal feed"
2366 msgstr ""
3498 msgstr ""
2367
3499
2368 #: rhodecode/templates/journal/journal.html:41
3500 #: rhodecode/templates/journal/journal.html:14
2369 msgid "following user"
3501 msgid "RSS journal feed"
3502 msgstr ""
3503
3504 #: rhodecode/templates/journal/journal.html:24
3505 #: rhodecode/templates/pullrequests/pullrequest.html:27
3506 msgid "Refresh"
3507 msgstr ""
3508
3509 #: rhodecode/templates/journal/journal.html:27
3510 #: rhodecode/templates/journal/public_journal.html:24
3511 msgid "RSS feed"
3512 msgstr ""
3513
3514 #: rhodecode/templates/journal/journal.html:30
3515 #: rhodecode/templates/journal/public_journal.html:27
3516 msgid "ATOM feed"
2370 msgstr ""
3517 msgstr ""
2371
3518
2372 #: rhodecode/templates/journal/journal.html:41
3519 #: rhodecode/templates/journal/journal.html:41
3520 msgid "Watched"
3521 msgstr ""
3522
3523 #: rhodecode/templates/journal/journal.html:46
3524 msgid "ADD"
3525 msgstr ""
3526
3527 #: rhodecode/templates/journal/journal.html:114
3528 msgid "following user"
3529 msgstr ""
3530
3531 #: rhodecode/templates/journal/journal.html:114
2373 msgid "user"
3532 msgid "user"
2374 msgstr ""
3533 msgstr ""
2375
3534
2376 #: rhodecode/templates/journal/journal.html:65
3535 #: rhodecode/templates/journal/journal.html:147
2377 msgid "You are not following any users or repositories"
3536 msgid "You are not following any users or repositories"
2378 msgstr ""
3537 msgstr ""
2379
3538
2380 #: rhodecode/templates/journal/journal_data.html:46
3539 #: rhodecode/templates/journal/journal_data.html:47
2381 msgid "No entries yet"
3540 msgid "No entries yet"
2382 msgstr ""
3541 msgstr ""
2383
3542
2384 #: rhodecode/templates/journal/public_journal.html:17
3543 #: rhodecode/templates/journal/public_journal.html:13
3544 msgid "ATOM public journal feed"
3545 msgstr ""
3546
3547 #: rhodecode/templates/journal/public_journal.html:14
3548 msgid "RSS public journal feed"
3549 msgstr ""
3550
3551 #: rhodecode/templates/journal/public_journal.html:21
2385 msgid "Public Journal"
3552 msgid "Public Journal"
2386 msgstr ""
3553 msgstr ""
2387
3554
2388 #: rhodecode/templates/search/search.html:7
3555 #: rhodecode/templates/pullrequests/pullrequest.html:4
2389 #: rhodecode/templates/search/search.html:26
3556 #: rhodecode/templates/pullrequests/pullrequest.html:12
2390 msgid "in repository: "
3557 msgid "New pull request"
2391 msgstr ""
3558 msgstr ""
2392
3559
2393 #: rhodecode/templates/search/search.html:9
3560 #: rhodecode/templates/pullrequests/pullrequest.html:28
2394 #: rhodecode/templates/search/search.html:28
3561 msgid "refresh overview"
2395 msgid "in all repositories"
3562 msgstr ""
2396 msgstr ""
3563
2397
3564 #: rhodecode/templates/pullrequests/pullrequest.html:66
2398 #: rhodecode/templates/search/search.html:42
3565 msgid "Detailed compare view"
3566 msgstr ""
3567
3568 #: rhodecode/templates/pullrequests/pullrequest.html:70
3569 #: rhodecode/templates/pullrequests/pullrequest_show.html:82
3570 msgid "Pull request reviewers"
3571 msgstr ""
3572
3573 #: rhodecode/templates/pullrequests/pullrequest.html:79
3574 #: rhodecode/templates/pullrequests/pullrequest_show.html:94
3575 msgid "owner"
3576 msgstr ""
3577
3578 #: rhodecode/templates/pullrequests/pullrequest.html:91
3579 #: rhodecode/templates/pullrequests/pullrequest_show.html:109
3580 msgid "Add reviewer to this pull request."
3581 msgstr ""
3582
3583 #: rhodecode/templates/pullrequests/pullrequest.html:97
3584 msgid "Create new pull request"
3585 msgstr ""
3586
3587 #: rhodecode/templates/pullrequests/pullrequest.html:106
3588 #: rhodecode/templates/pullrequests/pullrequest_show.html:25
3589 #: rhodecode/templates/pullrequests/pullrequest_show_all.html:33
3590 msgid "Title"
3591 msgstr ""
3592
3593 #: rhodecode/templates/pullrequests/pullrequest.html:115
3594 msgid "description"
3595 msgstr ""
3596
3597 #: rhodecode/templates/pullrequests/pullrequest.html:123
3598 msgid "Send pull request"
3599 msgstr ""
3600
3601 #: rhodecode/templates/pullrequests/pullrequest_show.html:23
3602 #, python-format
3603 msgid "Closed %s"
3604 msgstr ""
3605
3606 #: rhodecode/templates/pullrequests/pullrequest_show.html:31
3607 msgid "Status"
3608 msgstr ""
3609
3610 #: rhodecode/templates/pullrequests/pullrequest_show.html:36
3611 msgid "Pull request status"
3612 msgstr ""
3613
3614 #: rhodecode/templates/pullrequests/pullrequest_show.html:44
3615 msgid "Still not reviewed by"
3616 msgstr ""
3617
3618 #: rhodecode/templates/pullrequests/pullrequest_show.html:47
3619 #, python-format
3620 msgid "%d reviewer"
3621 msgid_plural "%d reviewers"
3622 msgstr[0] ""
3623 msgstr[1] ""
3624
3625 #: rhodecode/templates/pullrequests/pullrequest_show.html:54
3626 msgid "Created on"
3627 msgstr ""
3628
3629 #: rhodecode/templates/pullrequests/pullrequest_show.html:61
3630 msgid "Compare view"
3631 msgstr ""
3632
3633 #: rhodecode/templates/pullrequests/pullrequest_show.html:65
3634 msgid "Incoming changesets"
3635 msgstr ""
3636
3637 #: rhodecode/templates/pullrequests/pullrequest_show_all.html:4
3638 msgid "all pull requests"
3639 msgstr ""
3640
3641 #: rhodecode/templates/pullrequests/pullrequest_show_all.html:12
3642 msgid "All pull requests"
3643 msgstr ""
3644
3645 #: rhodecode/templates/pullrequests/pullrequest_show_all.html:27
3646 msgid "Closed"
3647 msgstr ""
3648
3649 #: rhodecode/templates/search/search.html:6
3650 #, python-format
3651 msgid "Search \"%s\" in repository: %s"
3652 msgstr ""
3653
3654 #: rhodecode/templates/search/search.html:8
3655 #, python-format
3656 msgid "Search \"%s\" in all repositories"
3657 msgstr ""
3658
3659 #: rhodecode/templates/search/search.html:12
3660 #: rhodecode/templates/search/search.html:32
3661 #, python-format
3662 msgid "Search in repository: %s"
3663 msgstr ""
3664
3665 #: rhodecode/templates/search/search.html:14
3666 #: rhodecode/templates/search/search.html:34
3667 msgid "Search in all repositories"
3668 msgstr ""
3669
3670 #: rhodecode/templates/search/search.html:48
2399 msgid "Search term"
3671 msgid "Search term"
2400 msgstr ""
3672 msgstr ""
2401
3673
2402 #: rhodecode/templates/search/search.html:54
3674 #: rhodecode/templates/search/search.html:60
2403 msgid "Search in"
3675 msgid "Search in"
2404 msgstr ""
3676 msgstr ""
2405
3677
2406 #: rhodecode/templates/search/search.html:57
3678 #: rhodecode/templates/search/search.html:63
2407 msgid "File contents"
3679 msgid "File contents"
2408 msgstr ""
3680 msgstr ""
2409
3681
2410 #: rhodecode/templates/search/search.html:59
3682 #: rhodecode/templates/search/search.html:64
3683 msgid "Commit messages"
3684 msgstr ""
3685
3686 #: rhodecode/templates/search/search.html:65
2411 msgid "File names"
3687 msgid "File names"
2412 msgstr ""
3688 msgstr ""
2413
3689
2414 #: rhodecode/templates/search/search_content.html:20
3690 #: rhodecode/templates/search/search_commit.html:35
3691 #: rhodecode/templates/search/search_content.html:21
2415 #: rhodecode/templates/search/search_path.html:15
3692 #: rhodecode/templates/search/search_path.html:15
2416 msgid "Permission denied"
3693 msgid "Permission denied"
2417 msgstr ""
3694 msgstr ""
2418
3695
2419 #: rhodecode/templates/settings/repo_fork.html:5
3696 #: rhodecode/templates/settings/repo_settings.html:5
2420 msgid "Fork"
3697 #, python-format
2421 msgstr ""
3698 msgid "%s Settings"
2422
2423 #: rhodecode/templates/settings/repo_fork.html:31
2424 msgid "Fork name"
2425 msgstr ""
2426
2427 #: rhodecode/templates/settings/repo_fork.html:55
2428 msgid "fork this repository"
2429 msgstr ""
3699 msgstr ""
2430
3700
2431 #: rhodecode/templates/shortlog/shortlog.html:5
3701 #: rhodecode/templates/shortlog/shortlog.html:5
2432 #: rhodecode/templates/summary/summary.html:666
3702 #, python-format
2433 msgid "Shortlog"
3703 msgid "%s Shortlog"
2434 msgstr ""
3704 msgstr ""
2435
3705
2436 #: rhodecode/templates/shortlog/shortlog.html:14
3706 #: rhodecode/templates/shortlog/shortlog.html:14
2437 msgid "shortlog"
3707 msgid "shortlog"
2438 msgstr ""
3708 msgstr ""
2439
3709
2440 #: rhodecode/templates/shortlog/shortlog_data.html:6
3710 #: rhodecode/templates/shortlog/shortlog_data.html:7
2441 msgid "age"
3711 msgid "age"
2442 msgstr ""
3712 msgstr ""
2443
3713
3714 #: rhodecode/templates/shortlog/shortlog_data.html:18
3715 msgid "No commit message"
3716 msgstr ""
3717
3718 #: rhodecode/templates/shortlog/shortlog_data.html:62
3719 msgid "Add or upload files directly via RhodeCode"
3720 msgstr ""
3721
3722 #: rhodecode/templates/shortlog/shortlog_data.html:71
3723 msgid "Push new repo"
3724 msgstr ""
3725
3726 #: rhodecode/templates/shortlog/shortlog_data.html:79
3727 msgid "Existing repository?"
3728 msgstr ""
3729
3730 #: rhodecode/templates/summary/summary.html:4
3731 #, python-format
3732 msgid "%s Summary"
3733 msgstr ""
3734
2444 #: rhodecode/templates/summary/summary.html:12
3735 #: rhodecode/templates/summary/summary.html:12
2445 msgid "summary"
3736 msgid "summary"
2446 msgstr ""
3737 msgstr ""
2447
3738
2448 #: rhodecode/templates/summary/summary.html:79
3739 #: rhodecode/templates/summary/summary.html:20
3740 #, python-format
3741 msgid "repo %s ATOM feed"
3742 msgstr ""
3743
3744 #: rhodecode/templates/summary/summary.html:21
3745 #, python-format
3746 msgid "repo %s RSS feed"
3747 msgstr ""
3748
3749 #: rhodecode/templates/summary/summary.html:49
3750 #: rhodecode/templates/summary/summary.html:52
3751 msgid "ATOM"
3752 msgstr ""
3753
3754 #: rhodecode/templates/summary/summary.html:82
3755 #, python-format
3756 msgid "Non changable ID %s"
3757 msgstr ""
3758
3759 #: rhodecode/templates/summary/summary.html:87
3760 msgid "public"
3761 msgstr ""
3762
3763 #: rhodecode/templates/summary/summary.html:95
2449 msgid "remote clone"
3764 msgid "remote clone"
2450 msgstr ""
3765 msgstr ""
2451
3766
2452 #: rhodecode/templates/summary/summary.html:121
3767 #: rhodecode/templates/summary/summary.html:116
2453 msgid "by"
3768 msgid "Contact"
2454 msgstr ""
3769 msgstr ""
2455
3770
2456 #: rhodecode/templates/summary/summary.html:128
3771 #: rhodecode/templates/summary/summary.html:130
2457 msgid "Clone url"
3772 msgid "Clone url"
2458 msgstr ""
3773 msgstr ""
2459
3774
2460 #: rhodecode/templates/summary/summary.html:137
3775 #: rhodecode/templates/summary/summary.html:133
2461 msgid "Trending source files"
3776 msgid "Show by Name"
2462 msgstr ""
3777 msgstr ""
2463
3778
2464 #: rhodecode/templates/summary/summary.html:146
3779 #: rhodecode/templates/summary/summary.html:134
2465 msgid "Download"
3780 msgid "Show by ID"
3781 msgstr ""
3782
3783 #: rhodecode/templates/summary/summary.html:142
3784 msgid "Trending files"
2466 msgstr ""
3785 msgstr ""
2467
3786
2468 #: rhodecode/templates/summary/summary.html:150
3787 #: rhodecode/templates/summary/summary.html:150
2469 msgid "There are no downloads yet"
3788 #: rhodecode/templates/summary/summary.html:166
2470 msgstr ""
3789 #: rhodecode/templates/summary/summary.html:194
2471
2472 #: rhodecode/templates/summary/summary.html:152
2473 msgid "Downloads are disabled for this repository"
2474 msgstr ""
2475
2476 #: rhodecode/templates/summary/summary.html:154
2477 #: rhodecode/templates/summary/summary.html:320
2478 msgid "enable"
3790 msgid "enable"
2479 msgstr ""
3791 msgstr ""
2480
3792
3793 #: rhodecode/templates/summary/summary.html:158
3794 msgid "Download"
3795 msgstr ""
3796
2481 #: rhodecode/templates/summary/summary.html:162
3797 #: rhodecode/templates/summary/summary.html:162
2482 #: rhodecode/templates/summary/summary.html:297
3798 msgid "There are no downloads yet"
3799 msgstr ""
3800
3801 #: rhodecode/templates/summary/summary.html:164
3802 msgid "Downloads are disabled for this repository"
3803 msgstr ""
3804
3805 #: rhodecode/templates/summary/summary.html:170
3806 msgid "Download as zip"
3807 msgstr ""
3808
3809 #: rhodecode/templates/summary/summary.html:173
3810 msgid "Check this to download archive with subrepos"
3811 msgstr ""
3812
3813 #: rhodecode/templates/summary/summary.html:173
3814 msgid "with subrepos"
3815 msgstr ""
3816
3817 #: rhodecode/templates/summary/summary.html:186
3818 msgid "Commit activity by day / author"
3819 msgstr ""
3820
3821 #: rhodecode/templates/summary/summary.html:197
3822 msgid "Stats gathered: "
3823 msgstr ""
3824
3825 #: rhodecode/templates/summary/summary.html:218
3826 msgid "Shortlog"
3827 msgstr ""
3828
3829 #: rhodecode/templates/summary/summary.html:220
3830 msgid "Quick start"
3831 msgstr ""
3832
3833 #: rhodecode/templates/summary/summary.html:233
3834 #, python-format
3835 msgid "Readme file at revision '%s'"
3836 msgstr ""
3837
3838 #: rhodecode/templates/summary/summary.html:236
3839 msgid "Permalink to this readme"
3840 msgstr ""
3841
3842 #: rhodecode/templates/summary/summary.html:293
2483 #, python-format
3843 #, python-format
2484 msgid "Download %s as %s"
3844 msgid "Download %s as %s"
2485 msgstr ""
3845 msgstr ""
2486
3846
2487 #: rhodecode/templates/summary/summary.html:168
3847 #: rhodecode/templates/summary/summary.html:650
2488 msgid "Check this to download archive with subrepos"
2489 msgstr ""
2490
2491 #: rhodecode/templates/summary/summary.html:168
2492 msgid "with subrepos"
2493 msgstr ""
2494
2495 #: rhodecode/templates/summary/summary.html:176
2496 msgid "Feeds"
2497 msgstr ""
2498
2499 #: rhodecode/templates/summary/summary.html:257
2500 #: rhodecode/templates/summary/summary.html:684
2501 #: rhodecode/templates/summary/summary.html:695
2502 msgid "show more"
2503 msgstr ""
2504
2505 #: rhodecode/templates/summary/summary.html:312
2506 msgid "Commit activity by day / author"
2507 msgstr ""
2508
2509 #: rhodecode/templates/summary/summary.html:324
2510 msgid "Loaded in"
2511 msgstr ""
2512
2513 #: rhodecode/templates/summary/summary.html:603
2514 msgid "commits"
3848 msgid "commits"
2515 msgstr ""
3849 msgstr ""
2516
3850
2517 #: rhodecode/templates/summary/summary.html:604
3851 #: rhodecode/templates/summary/summary.html:651
2518 msgid "files added"
3852 msgid "files added"
2519 msgstr ""
3853 msgstr ""
2520
3854
2521 #: rhodecode/templates/summary/summary.html:605
3855 #: rhodecode/templates/summary/summary.html:652
2522 msgid "files changed"
3856 msgid "files changed"
2523 msgstr ""
3857 msgstr ""
2524
3858
2525 #: rhodecode/templates/summary/summary.html:606
3859 #: rhodecode/templates/summary/summary.html:653
2526 msgid "files removed"
3860 msgid "files removed"
2527 msgstr ""
3861 msgstr ""
2528
3862
2529 #: rhodecode/templates/summary/summary.html:610
3863 #: rhodecode/templates/summary/summary.html:656
3864 msgid "commit"
3865 msgstr ""
3866
3867 #: rhodecode/templates/summary/summary.html:657
2530 msgid "file added"
3868 msgid "file added"
2531 msgstr ""
3869 msgstr ""
2532
3870
2533 #: rhodecode/templates/summary/summary.html:611
3871 #: rhodecode/templates/summary/summary.html:658
2534 msgid "file changed"
3872 msgid "file changed"
2535 msgstr ""
3873 msgstr ""
2536
3874
2537 #: rhodecode/templates/summary/summary.html:612
3875 #: rhodecode/templates/summary/summary.html:659
2538 msgid "file removed"
3876 msgid "file removed"
2539 msgstr ""
3877 msgstr ""
2540
3878
3879 #: rhodecode/templates/tags/tags.html:5
3880 #, python-format
3881 msgid "%s Tags"
3882 msgstr ""
3883
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/tests/test_models.py to rhodecode/tests/models/test_notifications.py
NO CONTENT: file renamed from rhodecode/tests/test_models.py to rhodecode/tests/models/test_notifications.py
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/tests/mem_watch to rhodecode/tests/scripts/mem_watch
NO CONTENT: file renamed from rhodecode/tests/mem_watch to rhodecode/tests/scripts/mem_watch
1 NO CONTENT: file renamed from rhodecode/tests/_test_concurency.py to rhodecode/tests/scripts/test_concurency.py
NO CONTENT: file renamed from rhodecode/tests/_test_concurency.py to rhodecode/tests/scripts/test_concurency.py
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from rhodecode/tests/rhodecode_crawler.py to rhodecode/tests/scripts/test_crawler.py
NO CONTENT: file renamed from rhodecode/tests/rhodecode_crawler.py to rhodecode/tests/scripts/test_crawler.py
1 NO CONTENT: file renamed from rhodecode/tests/test_hg_operations.py to rhodecode/tests/scripts/test_vcs_operations.py
NO CONTENT: file renamed from rhodecode/tests/test_hg_operations.py to rhodecode/tests/scripts/test_vcs_operations.py
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now