##// END OF EJS Templates
merged bugfixes for rhodecode 1.1.2 release
marcink -
r939:c165349f default
parent child Browse files
Show More
@@ -1,136 +1,151 b''
1 1 .. _changelog:
2 2
3 3 Changelog
4 4 =========
5 5
6 6 1.1.1 (**2011-01-06**)
7 7 ======================
8 8
9 9 news
10 10 ----
11 11
12 12 - added force https option into ini files for easier https usage (no need to
13 13 set server headers with this options)
14 14 - small css updates
15 15
16 16 fixes
17 17 -----
18 18
19 19 - fixed #96 redirect loop on files view on repositories without changesets
20 20 - fixed #97 unicode string passed into server header in special cases (mod_wsgi)
21 21 and server crashed with errors
22 22 - fixed large tooltips problems on main page
23 23 - fixed #92 whoosh indexer is more error proof
24 24
25 1.1.2 (**2011-01-12**)
26 ======================
27
28 news
29 ----
30
31
32 fixes
33 -----
34
35 - fixes #98 protection against float division of percentage stats
36 - fixed graph bug
37 - forced webhelpers version since it was making troubles during installation
38
39
25 40 1.1.0 (**2010-12-18**)
26 41 ======================
27 42
28 43 news
29 44 ----
30 45
31 46 - rewrite of internals for vcs >=0.1.10
32 47 - uses mercurial 1.7 with dotencode disabled for maintaining compatibility
33 48 with older clients
34 49 - anonymous access, authentication via ldap
35 50 - performance upgrade for cached repos list - each repository has it's own
36 51 cache that's invalidated when needed.
37 52 - performance upgrades on repositories with large amount of commits (20K+)
38 53 - main page quick filter for filtering repositories
39 54 - user dashboards with ability to follow chosen repositories actions
40 55 - sends email to admin on new user registration
41 56 - added cache/statistics reset options into repository settings
42 57 - more detailed action logger (based on hooks) with pushed changesets lists
43 58 and options to disable those hooks from admin panel
44 59 - introduced new enhanced changelog for merges that shows more accurate results
45 60 - new improved and faster code stats (based on pygments lexers mapping tables,
46 61 showing up to 10 trending sources for each repository. Additionally stats
47 62 can be disabled in repository settings.
48 63 - gui optimizations, fixed application width to 1024px
49 64 - added cut off (for large files/changesets) limit into config files
50 65 - whoosh, celeryd, upgrade moved to paster command
51 66 - other than sqlite database backends can be used
52 67
53 68 fixes
54 69 -----
55 70
56 71 - fixes #61 forked repo was showing only after cache expired
57 72 - fixes #76 no confirmation on user deletes
58 73 - fixes #66 Name field misspelled
59 74 - fixes #72 block user removal when he owns repositories
60 75 - fixes #69 added password confirmation fields
61 76 - fixes #87 RhodeCode crashes occasionally on updating repository owner
62 77 - fixes #82 broken annotations on files with more than 1 blank line at the end
63 78 - a lot of fixes and tweaks for file browser
64 79 - fixed detached session issues
65 80 - fixed when user had no repos he would see all repos listed in my account
66 81 - fixed ui() instance bug when global hgrc settings was loaded for server
67 82 instance and all hgrc options were merged with our db ui() object
68 83 - numerous small bugfixes
69 84
70 85 (special thanks for TkSoh for detailed feedback)
71 86
72 87
73 88 1.0.2 (**2010-11-12**)
74 89 ======================
75 90
76 91 news
77 92 ----
78 93
79 94 - tested under python2.7
80 95 - bumped sqlalchemy and celery versions
81 96
82 97 fixes
83 98 -----
84 99
85 100 - fixed #59 missing graph.js
86 101 - fixed repo_size crash when repository had broken symlinks
87 102 - fixed python2.5 crashes.
88 103
89 104
90 105 1.0.1 (**2010-11-10**)
91 106 ======================
92 107
93 108 news
94 109 ----
95 110
96 111 - small css updated
97 112
98 113 fixes
99 114 -----
100 115
101 116 - fixed #53 python2.5 incompatible enumerate calls
102 117 - fixed #52 disable mercurial extension for web
103 118 - fixed #51 deleting repositories don't delete it's dependent objects
104 119
105 120
106 121 1.0.0 (**2010-11-02**)
107 122 ======================
108 123
109 124 - security bugfix simplehg wasn't checking for permissions on commands
110 125 other than pull or push.
111 126 - fixed doubled messages after push or pull in admin journal
112 127 - templating and css corrections, fixed repo switcher on chrome, updated titles
113 128 - admin menu accessible from options menu on repository view
114 129 - permissions cached queries
115 130
116 131 1.0.0rc4 (**2010-10-12**)
117 132 ==========================
118 133
119 134 - fixed python2.5 missing simplejson imports (thanks to Jens BΓ€ckman)
120 135 - removed cache_manager settings from sqlalchemy meta
121 136 - added sqlalchemy cache settings to ini files
122 137 - validated password length and added second try of failure on paster setup-app
123 138 - fixed setup database destroy prompt even when there was no db
124 139
125 140
126 141 1.0.0rc3 (**2010-10-11**)
127 142 =========================
128 143
129 144 - fixed i18n during installation.
130 145
131 146 1.0.0rc2 (**2010-10-11**)
132 147 =========================
133 148
134 149 - Disabled dirsize in file browser, it's causing nasty bug when dir renames
135 150 occure. After vcs is fixed it'll be put back again.
136 151 - templating/css rewrites, optimized css. No newline at end of file
@@ -1,99 +1,99 b''
1 1 .. _installation:
2 2
3 3 Installation
4 4 ============
5 5
6 6 ``RhodeCode`` is written entirely in Python, but in order to use it's full
7 7 potential there are some third-party requirements. When RhodeCode is used
8 8 together with celery You have to install some kind of message broker,
9 9 recommended one is rabbitmq_ to make the async tasks work.
10 10
11 11 Of course RhodeCode works in sync mode also, then You don't have to install
12 12 any third party apps. Celery_ will give You large speed improvement when using
13 13 many big repositories. If You plan to use it for 7 or 10 small repositories, it
14 14 will work just fine without celery running.
15 15
16 16 After You decide to Run it with celery make sure You run celeryd using paster
17 17 and message broker together with the application.
18 18
19 19 Install from Cheese Shop
20 20 ------------------------
21 21 Rhodecode requires python 2.x greater than version 2.5
22 22
23 23 Easiest way to install ``rhodecode`` is to run::
24 24
25 25 easy_install rhodecode
26 26
27 27 Or::
28 28
29 29 pip install rhodecode
30 30
31 31 If you prefer to install manually simply grab latest release from
32 http://pypi.python.org/pypi/rhodecode, decompres archive and run::
32 http://pypi.python.org/pypi/RhodeCode, decompres archive and run::
33 33
34 34 python setup.py install
35 35
36 36
37 37 Step by step installation example
38 38 ---------------------------------
39 39
40 40
41 41 - Assuming You have installed virtualenv_ create one using.
42 42 The `--no-site-packages` will make sure non of Your system libs are linked
43 43 with this virtualenv_
44 44
45 45 ::
46 46
47 47 virtualenv --no-site-packages /var/www/rhodecode-venv
48 48
49 49 - this will install new virtualenv_ into `/var/www/rhodecode-venv`.
50 50 - Activate the virtualenv_ by running
51 51
52 52 ::
53 53
54 54 source /var/www/rhodecode-venv/bin/activate
55 55
56 56 - Make a folder for rhodecode somewhere on the filesystem for example
57 57
58 58 ::
59 59
60 60 mkdir /var/www/rhodecode
61 61
62 62
63 63 - Run this command to install rhodecode
64 64
65 65 ::
66 66
67 67 easy_install rhodecode
68 68
69 69 - this will install rhodecode together with pylons
70 70 and all other required python libraries
71 71
72 72 Requirements for Celery (optional)
73 73 ----------------------------------
74 74
75 75 .. note::
76 76 Installing message broker and using celery is optional, RhodeCode will
77 77 work without them perfectly fine.
78 78
79 79
80 80 **Message Broker**
81 81
82 82 - preferred is `RabbitMq <http://www.rabbitmq.com/>`_
83 83 - possible other is `Redis <http://code.google.com/p/redis/>`_
84 84
85 85 For installation instructions You can visit:
86 86 http://ask.github.com/celery/getting-started/index.html
87 87 It's very nice tutorial how to start celery_ with rabbitmq_
88 88
89 89
90 90 You can now proceed to :ref:`setup`
91 91 -----------------------------------
92 92
93 93
94 94
95 95 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
96 96 .. _python: http://www.python.org/
97 97 .. _mercurial: http://mercurial.selenic.com/
98 98 .. _celery: http://celeryproject.org/
99 99 .. _rabbitmq: http://www.rabbitmq.com/ No newline at end of file
@@ -1,299 +1,302 b''
1 1 .. _setup:
2 2
3 3 Setup
4 4 =====
5 5
6 6
7 7 Setting up the application
8 8 --------------------------
9 9
10 10 First You'll ned to create RhodeCode config file. Run the following command
11 11 to do this
12 12
13 13 ::
14 14
15 15 paster make-config RhodeCode production.ini
16 16
17 17 - This will create `production.ini` config inside the directory
18 18 this config contains various settings for RhodeCode, e.g proxy port,
19 19 email settings, usage of static files, cache, celery settings and logging.
20 20
21 21
22 22
23 23 Next we need to create the database.
24 24
25 25 ::
26 26
27 27 paster setup-app production.ini
28 28
29 29 - This command will create all needed tables and an admin account.
30 30 When asked for a path You can either use a new location of one with already
31 31 existing ones. RhodeCode will simply add all new found repositories to
32 32 it's database. Also make sure You specify correct path to repositories.
33 33 - Remember that the given path for mercurial_ repositories must be write
34 34 accessible for the application. It's very important since RhodeCode web
35 35 interface will work even without such an access but, when trying to do a
36 36 push it'll eventually fail with permission denied errors.
37 37
38 38 You are ready to use rhodecode, to run it simply execute
39 39
40 40 ::
41 41
42 42 paster serve production.ini
43 43
44 44 - This command runs the RhodeCode server the app should be available at the
45 45 127.0.0.1:5000. This ip and port is configurable via the production.ini
46 46 file created in previous step
47 47 - Use admin account you created to login.
48 48 - Default permissions on each repository is read, and owner is admin. So
49 49 remember to update these if needed. In the admin panel You can toggle ldap,
50 50 anonymous, permissions settings. As well as edit more advanced options on
51 51 users and repositories
52 52
53 53
54 54 Setting up Whoosh full text search
55 55 ----------------------------------
56 56
57 57 Index for whoosh can be build starting from version 1.1 using paster command
58 58 passing repo locations to index, as well as Your config file that stores
59 59 whoosh index files locations. There is possible to pass `-f` to the options
60 60 to enable full index rebuild. Without that indexing will run always in in
61 61 incremental mode.
62 62
63 63 ::
64 64
65 65 paster make-index production.ini --repo-location=<location for repos>
66 66
67 67 for full index rebuild You can use
68 68
69 69 ::
70 70
71 71 paster make-index production.ini -f --repo-location=<location for repos>
72 72
73 73 - For full text search You can either put crontab entry for
74 74
75 75 This command can be run even from crontab in order to do periodical
76 76 index builds and keep Your index always up to date. An example entry might
77 77 look like this
78 78
79 79 ::
80 80
81 81 /path/to/python/bin/paster /path/to/rhodecode/production.ini --repo-location=<location for repos>
82 82
83 83 When using incremental(default) mode whoosh will check last modification date
84 84 of each file and add it to reindex if newer file is available. Also indexing
85 85 daemon checks for removed files and removes them from index.
86 86
87 87 Sometime You might want to rebuild index from scratch. You can do that using
88 88 the `-f` flag passed to paster command or, in admin panel You can check
89 89 `build from scratch` flag.
90 90
91 91
92 92 Setting up LDAP support
93 93 -----------------------
94 94
95 95 RhodeCode starting from version 1.1 supports ldap authentication. In order
96 96 to use ldap, You have to install python-ldap package. This package is available
97 97 via pypi, so You can install it by running
98 98
99 99 ::
100 100
101 101 easy_install python-ldap
102 102
103 103 ::
104 104
105 105 pip install python-ldap
106 106
107 107 .. note::
108 108 python-ldap requires some certain libs on Your system, so before installing
109 109 it check that You have at least `openldap`, and `sasl` libraries.
110 110
111 111 ldap settings are located in admin->ldap section,
112 112
113 113 Here's a typical ldap setup::
114 114
115 115 Enable ldap = checked #controls if ldap access is enabled
116 116 Host = host.domain.org #actual ldap server to connect
117 117 Port = 389 or 689 for ldaps #ldap server ports
118 118 Enable LDAPS = unchecked #enable disable ldaps
119 119 Account = <account> #access for ldap server(if required)
120 120 Password = <password> #password for ldap server(if required)
121 121 Base DN = uid=%(user)s,CN=users,DC=host,DC=domain,DC=org
122 122
123 123
124 124 `Account` and `Password` are optional, and used for two-phase ldap
125 125 authentication so those are credentials to access Your ldap, if it doesn't
126 126 support anonymous search/user lookups.
127 127
128 128 Base DN must have %(user)s template inside, it's a placer where Your uid used
129 129 to login would go, it allows admins to specify not standard schema for uid
130 130 variable
131 131
132 132 If all data are entered correctly, and `python-ldap` is properly installed
133 133 Users should be granted to access RhodeCode wit ldap accounts. When
134 134 logging at the first time an special ldap account is created inside RhodeCode,
135 135 so You can control over permissions even on ldap users. If such user exists
136 136 already in RhodeCode database ldap user with the same username would be not
137 137 able to access RhodeCode.
138 138
139 139 If You have problems with ldap access and believe You entered correct
140 140 information check out the RhodeCode logs,any error messages sent from
141 141 ldap will be saved there.
142 142
143 143
144 144
145 145 Setting Up Celery
146 146 -----------------
147 147
148 148 Since version 1.1 celery is configured by the rhodecode ini configuration files
149 149 simply set use_celery=true in the ini file then add / change the configuration
150 150 variables inside the ini file.
151 151
152 152 Remember that the ini files uses format with '.' not with '_' like celery
153 153 so for example setting `BROKER_HOST` in celery means setting `broker.host` in
154 154 the config file.
155 155
156 156 In order to make start using celery run::
157
157 158 paster celeryd <configfile.ini>
158 159
159
160 .. note::
161 Make sure You run this command from same virtualenv, and with the same user
162 that rhodecode runs.
163
160 164 HTTPS support
161 165 -------------
162 166
163 167 There are two ways to enable https, first is to set HTTP_X_URL_SCHEME in
164 168 Your http server headers, than rhodecode will recognise this headers and make
165 169 proper https redirections, another way is to set `force_https = true`
166 170 in the ini cofiguration to force using https, no headers are needed than to
167 171 enable https
168 172
169 173
170 174 Nginx virtual host example
171 175 --------------------------
172 176
173 177 Sample config for nginx using proxy::
174 178
175 179 server {
176 180 listen 80;
177 181 server_name hg.myserver.com;
178 182 access_log /var/log/nginx/rhodecode.access.log;
179 183 error_log /var/log/nginx/rhodecode.error.log;
180 184 location / {
181 185 root /var/www/rhodecode/rhodecode/public/;
182 186 if (!-f $request_filename){
183 187 proxy_pass http://127.0.0.1:5000;
184 188 }
185 #this is important for https !!!
189 #this is important if You want to use https !!!
186 190 proxy_set_header X-Url-Scheme $scheme;
187 191 include /etc/nginx/proxy.conf;
188 192 }
189 193 }
190 194
191 195 Here's the proxy.conf. It's tuned so it'll not timeout on long
192 196 pushes and also on large pushes::
193 197
194 198 proxy_redirect off;
195 199 proxy_set_header Host $host;
196 200 proxy_set_header X-Host $http_host;
197 201 proxy_set_header X-Real-IP $remote_addr;
198 202 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
199 203 proxy_set_header Proxy-host $proxy_host;
200 204 client_max_body_size 400m;
201 205 client_body_buffer_size 128k;
202 206 proxy_buffering off;
203 207 proxy_connect_timeout 3600;
204 208 proxy_send_timeout 3600;
205 209 proxy_read_timeout 3600;
206 210 proxy_buffer_size 8k;
207 211 proxy_buffers 8 32k;
208 212 proxy_busy_buffers_size 64k;
209 213 proxy_temp_file_write_size 64k;
210 214
211 215 Also when using root path with nginx You might set the static files to false
212 216 in production.ini file::
213 217
214 218 [app:main]
215 219 use = egg:rhodecode
216 220 full_stack = true
217 221 static_files = false
218 222 lang=en
219 223 cache_dir = %(here)s/data
220 224
221 225 To not have the statics served by the application. And improve speed.
222 226
223 227
224 228 Apache virtual host example
225 229 ---------------------------
226 230
227 231 Sample config for apache using proxy::
228 232
229 233 <VirtualHost *:80>
230 234 ServerName hg.myserver.com
231 235 ServerAlias hg.myserver.com
232 236
233 237 <Proxy *>
234 238 Order allow,deny
235 239 Allow from all
236 240 </Proxy>
237 241
238 242 #important !
239 243 #Directive to properly generate url (clone url) for pylons
240 244 ProxyPreserveHost On
241 245
242 246 #rhodecode instance
243 247 ProxyPass / http://127.0.0.1:5000/
244 248 ProxyPassReverse / http://127.0.0.1:5000/
245 249
246 250 #to enable https use line below
247 251 #SetEnvIf X-Url-Scheme https HTTPS=1
248 252
249 253 </VirtualHost>
250 254
251 255
252 256 Additional tutorial
253 257 http://wiki.pylonshq.com/display/pylonscookbook/Apache+as+a+reverse+proxy+for+Pylons
254 258
255 259
256 260 Apache's example FCGI config
257 261 ----------------------------
258 262
259 263 TODO !
260 264
261 265 Other configuration files
262 266 -------------------------
263 267
264 Some extra configuration files and examples can be found here:
265 http://hg.python-works.com/rhodecode/files/tip/init.d
268 Some example init.d script can be found here, for debian and gentoo:
266 269
267 and also an celeryconfig file can be use from here:
268 http://hg.python-works.com/rhodecode/files/tip/celeryconfig.py
270 https://rhodeocode.org/rhodecode/files/tip/init.d
271
269 272
270 273 Troubleshooting
271 274 ---------------
272 275
273 276 - missing static files ?
274 277
275 278 - make sure either to set the `static_files = true` in the .ini file or
276 279 double check the root path for Your http setup. It should point to
277 280 for example:
278 281 /home/my-virtual-python/lib/python2.6/site-packages/rhodecode/public
279 282
280 283 - can't install celery/rabbitmq
281 284
282 285 - don't worry RhodeCode works without them too. No extra setup required
283 286
284 287 - long lasting push timeouts ?
285 288
286 289 - make sure You set a longer timeouts in Your proxy/fcgi settings, timeouts
287 290 are caused by https server and not RhodeCode
288 291
289 292 - large pushes timeouts ?
290 293
291 294 - make sure You set a proper max_body_size for the http server
292 295
293 296
294 297
295 298 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
296 299 .. _python: http://www.python.org/
297 300 .. _mercurial: http://mercurial.selenic.com/
298 301 .. _celery: http://celeryproject.org/
299 302 .. _rabbitmq: http://www.rabbitmq.com/ No newline at end of file
@@ -1,313 +1,313 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.admin.repos
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Admin controller for RhodeCode
7 7
8 8 :created_on: Apr 7, 2010
9 9 :author: marcink
10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software; you can redistribute it and/or
14 14 # modify it under the terms of the GNU General Public License
15 15 # as published by the Free Software Foundation; version 2
16 16 # of the License or (at your opinion) any later version of the license.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program; if not, write to the Free Software
25 25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 26 # MA 02110-1301, USA.
27 27
28 28 import logging
29 29 import traceback
30 30 import formencode
31 31 from operator import itemgetter
32 32 from formencode import htmlfill
33 33
34 34 from paste.httpexceptions import HTTPInternalServerError
35 35 from pylons import request, response, session, tmpl_context as c, url
36 36 from pylons.controllers.util import abort, redirect
37 37 from pylons.i18n.translation import _
38 38
39 39 from rhodecode.lib import helpers as h
40 40 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
41 41 HasPermissionAnyDecorator
42 42 from rhodecode.lib.base import BaseController, render
43 43 from rhodecode.lib.utils import invalidate_cache, action_logger
44 44 from rhodecode.model.db import User
45 45 from rhodecode.model.forms import RepoForm
46 46 from rhodecode.model.scm import ScmModel
47 47 from rhodecode.model.repo import RepoModel
48 48
49 49
50 50 log = logging.getLogger(__name__)
51 51
52 52 class ReposController(BaseController):
53 53 """REST Controller styled on the Atom Publishing Protocol"""
54 54 # To properly map this controller, ensure your config/routing.py
55 55 # file has a resource setup:
56 56 # map.resource('repo', 'repos')
57 57
58 58 @LoginRequired()
59 59 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
60 60 def __before__(self):
61 61 c.admin_user = session.get('admin_user')
62 62 c.admin_username = session.get('admin_username')
63 63 super(ReposController, self).__before__()
64 64
65 65 @HasPermissionAllDecorator('hg.admin')
66 66 def index(self, format='html'):
67 67 """GET /repos: All items in the collection"""
68 68 # url('repos')
69 69 cached_repo_list = ScmModel().get_repos()
70 70 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
71 71 return render('admin/repos/repos.html')
72 72
73 73 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
74 74 def create(self):
75 75 """POST /repos: Create a new item"""
76 76 # url('repos')
77 77 repo_model = RepoModel()
78 78 _form = RepoForm()()
79 79 form_result = {}
80 80 try:
81 81 form_result = _form.to_python(dict(request.POST))
82 82 repo_model.create(form_result, c.rhodecode_user)
83 83 h.flash(_('created repository %s') % form_result['repo_name'],
84 84 category='success')
85 85
86 86 if request.POST.get('user_created'):
87 87 action_logger(self.rhodecode_user, 'user_created_repo',
88 88 form_result['repo_name'], '', self.sa)
89 89 else:
90 90 action_logger(self.rhodecode_user, 'admin_created_repo',
91 91 form_result['repo_name'], '', self.sa)
92 92
93 93 except formencode.Invalid, errors:
94 94 c.new_repo = errors.value['repo_name']
95 95
96 96 if request.POST.get('user_created'):
97 97 r = render('admin/repos/repo_add_create_repository.html')
98 98 else:
99 99 r = render('admin/repos/repo_add.html')
100 100
101 101 return htmlfill.render(
102 102 r,
103 103 defaults=errors.value,
104 104 errors=errors.error_dict or {},
105 105 prefix_error=False,
106 106 encoding="UTF-8")
107 107
108 108 except Exception:
109 109 log.error(traceback.format_exc())
110 110 msg = _('error occurred during creation of repository %s') \
111 111 % form_result.get('repo_name')
112 112 h.flash(msg, category='error')
113 113 if request.POST.get('user_created'):
114 114 return redirect(url('home'))
115 115 return redirect(url('repos'))
116 116
117 117 @HasPermissionAllDecorator('hg.admin')
118 118 def new(self, format='html'):
119 119 """GET /repos/new: Form to create a new item"""
120 120 new_repo = request.GET.get('repo', '')
121 121 c.new_repo = h.repo_name_slug(new_repo)
122 122
123 123 return render('admin/repos/repo_add.html')
124 124
125 125 @HasPermissionAllDecorator('hg.admin')
126 126 def update(self, repo_name):
127 127 """PUT /repos/repo_name: Update an existing item"""
128 128 # Forms posted to this method should contain a hidden field:
129 129 # <input type="hidden" name="_method" value="PUT" />
130 130 # Or using helpers:
131 131 # h.form(url('repo', repo_name=ID),
132 132 # method='put')
133 133 # url('repo', repo_name=ID)
134 134 repo_model = RepoModel()
135 135 changed_name = repo_name
136 136 _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
137 137
138 138 try:
139 139 form_result = _form.to_python(dict(request.POST))
140 140 repo_model.update(repo_name, form_result)
141 141 invalidate_cache('get_repo_cached_%s' % repo_name)
142 142 h.flash(_('Repository %s updated successfully' % repo_name),
143 143 category='success')
144 144 changed_name = form_result['repo_name']
145 145 action_logger(self.rhodecode_user, 'admin_updated_repo',
146 146 changed_name, '', self.sa)
147 147
148 148 except formencode.Invalid, errors:
149 149 c.repo_info = repo_model.get_by_repo_name(repo_name)
150 150 if c.repo_info.stats:
151 151 last_rev = c.repo_info.stats.stat_on_revision
152 152 else:
153 153 last_rev = 0
154 154 c.stats_revision = last_rev
155 155 r = ScmModel().get(repo_name)
156 156 c.repo_last_rev = r.revisions[-1] if r.revisions else 0
157 157
158 158 if last_rev == 0:
159 159 c.stats_percentage = 0
160 160 else:
161 161 c.stats_percentage = '%.2f' % ((float((last_rev)) /
162 162 c.repo_last_rev) * 100)
163 163
164 164 c.users_array = repo_model.get_users_js()
165 165 errors.value.update({'user':c.repo_info.user.username})
166 166 return htmlfill.render(
167 167 render('admin/repos/repo_edit.html'),
168 168 defaults=errors.value,
169 169 errors=errors.error_dict or {},
170 170 prefix_error=False,
171 171 encoding="UTF-8")
172 172
173 173 except Exception:
174 174 log.error(traceback.format_exc())
175 175 h.flash(_('error occurred during update of repository %s') \
176 176 % repo_name, category='error')
177 177
178 178 return redirect(url('edit_repo', repo_name=changed_name))
179 179
180 180 @HasPermissionAllDecorator('hg.admin')
181 181 def delete(self, repo_name):
182 182 """DELETE /repos/repo_name: Delete an existing item"""
183 183 # Forms posted to this method should contain a hidden field:
184 184 # <input type="hidden" name="_method" value="DELETE" />
185 185 # Or using helpers:
186 186 # h.form(url('repo', repo_name=ID),
187 187 # method='delete')
188 188 # url('repo', repo_name=ID)
189 189
190 190 repo_model = RepoModel()
191 191 repo = repo_model.get_by_repo_name(repo_name)
192 192 if not repo:
193 193 h.flash(_('%s repository is not mapped to db perhaps'
194 194 ' it was moved or renamed from the filesystem'
195 195 ' please run the application again'
196 196 ' in order to rescan repositories') % repo_name,
197 197 category='error')
198 198
199 199 return redirect(url('repos'))
200 200 try:
201 201 action_logger(self.rhodecode_user, 'admin_deleted_repo',
202 202 repo_name, '', self.sa)
203 203 repo_model.delete(repo)
204 204 invalidate_cache('get_repo_cached_%s' % repo_name)
205 205 h.flash(_('deleted repository %s') % repo_name, category='success')
206 206
207 207 except Exception, e:
208 208 log.error(traceback.format_exc())
209 209 h.flash(_('An error occurred during deletion of %s') % repo_name,
210 210 category='error')
211 211
212 212 return redirect(url('repos'))
213 213
214 214 @HasPermissionAllDecorator('hg.admin')
215 215 def delete_perm_user(self, repo_name):
216 216 """
217 217 DELETE an existing repository permission user
218 218 :param repo_name:
219 219 """
220 220
221 221 try:
222 222 repo_model = RepoModel()
223 223 repo_model.delete_perm_user(request.POST, repo_name)
224 224 except Exception, e:
225 225 h.flash(_('An error occurred during deletion of repository user'),
226 226 category='error')
227 227 raise HTTPInternalServerError()
228 228
229 229 @HasPermissionAllDecorator('hg.admin')
230 230 def repo_stats(self, repo_name):
231 231 """
232 232 DELETE an existing repository statistics
233 233 :param repo_name:
234 234 """
235 235
236 236 try:
237 237 repo_model = RepoModel()
238 238 repo_model.delete_stats(repo_name)
239 239 except Exception, e:
240 240 h.flash(_('An error occurred during deletion of repository stats'),
241 241 category='error')
242 242 return redirect(url('edit_repo', repo_name=repo_name))
243 243
244 244 @HasPermissionAllDecorator('hg.admin')
245 245 def repo_cache(self, repo_name):
246 246 """
247 247 INVALIDATE existing repository cache
248 248 :param repo_name:
249 249 """
250 250
251 251 try:
252 252 ScmModel().mark_for_invalidation(repo_name)
253 253 except Exception, e:
254 254 h.flash(_('An error occurred during cache invalidation'),
255 255 category='error')
256 256 return redirect(url('edit_repo', repo_name=repo_name))
257 257
258 258 @HasPermissionAllDecorator('hg.admin')
259 259 def show(self, repo_name, format='html'):
260 260 """GET /repos/repo_name: Show a specific item"""
261 261 # url('repo', repo_name=ID)
262 262
263 263 @HasPermissionAllDecorator('hg.admin')
264 264 def edit(self, repo_name, format='html'):
265 265 """GET /repos/repo_name/edit: Form to edit an existing item"""
266 266 # url('edit_repo', repo_name=ID)
267 267 repo_model = RepoModel()
268 268 r = ScmModel().get(repo_name)
269 269 c.repo_info = repo_model.get_by_repo_name(repo_name)
270 270
271 271 if c.repo_info is None:
272 272 h.flash(_('%s repository is not mapped to db perhaps'
273 273 ' it was created or renamed from the filesystem'
274 274 ' please run the application again'
275 275 ' in order to rescan repositories') % repo_name,
276 276 category='error')
277 277
278 278 return redirect(url('repos'))
279 279
280 280 if c.repo_info.stats:
281 281 last_rev = c.repo_info.stats.stat_on_revision
282 282 else:
283 283 last_rev = 0
284 284 c.stats_revision = last_rev
285 285
286 286 c.repo_last_rev = r.revisions[-1] if r.revisions else 0
287 287
288 if last_rev == 0:
288 if last_rev == 0 or c.repo_last_rev == 0:
289 289 c.stats_percentage = 0
290 290 else:
291 291 c.stats_percentage = '%.2f' % ((float((last_rev)) /
292 292 c.repo_last_rev) * 100)
293 293
294 294 defaults = c.repo_info.get_dict()
295 295 if c.repo_info.user:
296 296 defaults.update({'user':c.repo_info.user.username})
297 297 else:
298 298 replacement_user = self.sa.query(User)\
299 299 .filter(User.admin == True).first().username
300 300 defaults.update({'user':replacement_user})
301 301
302 302 c.users_array = repo_model.get_users_js()
303 303
304 304 for p in c.repo_info.repo_to_perm:
305 305 defaults.update({'perm_%s' % p.user.username:
306 306 p.permission.permission_name})
307 307
308 308 return htmlfill.render(
309 309 render('admin/repos/repo_edit.html'),
310 310 defaults=defaults,
311 311 encoding="UTF-8",
312 312 force_defaults=False
313 313 )
@@ -1,144 +1,143 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.summary
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Summary controller for Rhodecode
7 7
8 8 :created_on: Apr 18, 2010
9 9 :author: marcink
10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software; you can redistribute it and/or
14 14 # modify it under the terms of the GNU General Public License
15 15 # as published by the Free Software Foundation; version 2
16 16 # of the License or (at your opinion) any later version of the license.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program; if not, write to the Free Software
25 25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 26 # MA 02110-1301, USA.
27 27
28 28 import calendar
29 29 import logging
30 30 from time import mktime
31 from datetime import datetime, timedelta
31 from datetime import datetime, timedelta, date
32 32
33 33 from vcs.exceptions import ChangesetError
34 34
35 35 from pylons import tmpl_context as c, request, url
36 36 from pylons.i18n.translation import _
37 37
38 38 from rhodecode.model.scm import ScmModel
39 39 from rhodecode.model.db import Statistics
40 40
41 41 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
42 42 from rhodecode.lib.base import BaseController, render
43 43 from rhodecode.lib.utils import OrderedDict, EmptyChangeset
44 44
45 45 from rhodecode.lib.celerylib import run_task
46 46 from rhodecode.lib.celerylib.tasks import get_commits_stats
47 47
48 48 from webhelpers.paginate import Page
49 49
50 50 try:
51 51 import json
52 52 except ImportError:
53 53 #python 2.5 compatibility
54 54 import simplejson as json
55 55 log = logging.getLogger(__name__)
56 56
57 57 class SummaryController(BaseController):
58 58
59 59 @LoginRequired()
60 60 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
61 61 'repository.admin')
62 62 def __before__(self):
63 63 super(SummaryController, self).__before__()
64 64
65 65 def index(self):
66 66 scm_model = ScmModel()
67 67 c.repo_info = scm_model.get_repo(c.repo_name)
68 68 c.following = scm_model.is_following_repo(c.repo_name,
69 69 c.rhodecode_user.user_id)
70 70 def url_generator(**kw):
71 71 return url('shortlog_home', repo_name=c.repo_name, **kw)
72 72
73 73 c.repo_changesets = Page(c.repo_info, page=1, items_per_page=10,
74 74 url=url_generator)
75 75
76 76 e = request.environ
77 77
78 78 if self.rhodecode_user.username == 'default':
79 79 password = ':default'
80 80 else:
81 81 password = ''
82 82
83 83 uri = u'%(protocol)s://%(user)s%(password)s@%(host)s%(prefix)s/%(repo_name)s' % {
84 84 'protocol': e.get('wsgi.url_scheme'),
85 85 'user':str(c.rhodecode_user.username),
86 86 'password':password,
87 87 'host':e.get('HTTP_HOST'),
88 88 'prefix':e.get('SCRIPT_NAME'),
89 89 'repo_name':c.repo_name, }
90 90 c.clone_repo_url = uri
91 91 c.repo_tags = OrderedDict()
92 92 for name, hash in c.repo_info.tags.items()[:10]:
93 93 try:
94 94 c.repo_tags[name] = c.repo_info.get_changeset(hash)
95 95 except ChangesetError:
96 96 c.repo_tags[name] = EmptyChangeset(hash)
97 97
98 98 c.repo_branches = OrderedDict()
99 99 for name, hash in c.repo_info.branches.items()[:10]:
100 100 try:
101 101 c.repo_branches[name] = c.repo_info.get_changeset(hash)
102 102 except ChangesetError:
103 103 c.repo_branches[name] = EmptyChangeset(hash)
104 104
105 td = datetime.today() + timedelta(days=1)
106 y, m, d = td.year, td.month, td.day
105 td = date.today() + timedelta(days=1)
106 td_1m = td - timedelta(days=calendar.mdays[td.month])
107 td_1y = td - timedelta(days=365)
107 108
108 ts_min_y = mktime((y - 1, (td - timedelta(days=calendar.mdays[m])).month,
109 d, 0, 0, 0, 0, 0, 0,))
110 ts_min_m = mktime((y, (td - timedelta(days=calendar.mdays[m])).month,
111 d, 0, 0, 0, 0, 0, 0,))
109 ts_min_m = mktime(td_1m.timetuple())
110 ts_min_y = mktime(td_1y.timetuple())
111 ts_max_y = mktime(td.timetuple())
112 112
113 ts_max_y = mktime((y, m, d, 0, 0, 0, 0, 0, 0,))
114 113 if c.repo_info.dbrepo.enable_statistics:
115 114 c.no_data_msg = _('No data loaded yet')
116 115 run_task(get_commits_stats, c.repo_info.name, ts_min_y, ts_max_y)
117 116 else:
118 117 c.no_data_msg = _('Statistics update are disabled for this repository')
119 118 c.ts_min = ts_min_m
120 119 c.ts_max = ts_max_y
121 120
122 121 stats = self.sa.query(Statistics)\
123 122 .filter(Statistics.repository == c.repo_info.dbrepo)\
124 123 .scalar()
125 124
126 125
127 126 if stats and stats.languages:
128 127 c.no_data = False is c.repo_info.dbrepo.enable_statistics
129 128 lang_stats = json.loads(stats.languages)
130 129 c.commit_data = stats.commit_activity
131 130 c.overview_data = stats.commit_activity_combined
132 131 c.trending_languages = json.dumps(OrderedDict(
133 132 sorted(lang_stats.items(), reverse=True,
134 133 key=lambda k: k[1])[:10]
135 134 )
136 135 )
137 136 else:
138 137 c.commit_data = json.dumps({})
139 138 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10] ])
140 139 c.trending_languages = json.dumps({})
141 140 c.no_data = True
142 141
143 142 return render('summary/summary.html')
144 143
@@ -1,103 +1,104 b''
1 1 import sys
2 2 py_version = sys.version_info
3 3
4 4 from rhodecode import get_version
5 5
6 6 requirements = [
7 7 "Pylons==1.0.0",
8 "WebHelpers>=1.2",
8 9 "SQLAlchemy==0.6.5",
9 10 "Mako==0.3.6",
10 11 "vcs==0.1.10",
11 12 "pygments==1.3.1",
12 13 "mercurial==1.7.2",
13 14 "whoosh==1.3.4",
14 15 "celery==2.1.4",
15 16 "py-bcrypt",
16 17 "babel",
17 18 ]
18 19
19 20 classifiers = ['Development Status :: 5 - Production/Stable',
20 21 'Environment :: Web Environment',
21 22 'Framework :: Pylons',
22 23 'Intended Audience :: Developers',
23 24 'License :: OSI Approved :: BSD License',
24 25 'Operating System :: OS Independent',
25 26 'Programming Language :: Python', ]
26 27
27 28 if sys.version_info < (2, 6):
28 29 requirements.append("simplejson")
29 30 requirements.append("pysqlite")
30 31
31 32 #additional files from project that goes somewhere in the filesystem
32 33 #relative to sys.prefix
33 34 data_files = []
34 35
35 36 #additional files that goes into package itself
36 37 package_data = {'rhodecode': ['i18n/*/LC_MESSAGES/*.mo', ], }
37 38
38 39 description = ('Mercurial repository browser/management with '
39 40 'build in push/pull server and full text search')
40 41 #long description
41 42 try:
42 43 readme_file = 'README.rst'
43 44 changelog_file = 'docs/changelog.rst'
44 45 long_description = open(readme_file).read() + '\n\n' + \
45 46 open(changelog_file).read()
46 47
47 48 except IOError, err:
48 49 sys.stderr.write("[WARNING] Cannot find file specified as "
49 50 "long_description (%s)\n or changelog (%s) skipping that file" \
50 51 % (readme_file, changelog_file))
51 52 long_description = description
52 53
53 54
54 55 try:
55 56 from setuptools import setup, find_packages
56 57 except ImportError:
57 58 from ez_setup import use_setuptools
58 59 use_setuptools()
59 60 from setuptools import setup, find_packages
60 61 #packages
61 62 packages = find_packages(exclude=['ez_setup'])
62 63
63 64 setup(
64 65 name='RhodeCode',
65 66 version=get_version(),
66 67 description=description,
67 68 long_description=long_description,
68 69 keywords='rhodiumcode mercurial web hgwebdir gitweb git replacement serving hgweb rhodecode',
69 70 license='BSD',
70 71 author='Marcin Kuzminski',
71 72 author_email='marcin@python-works.com',
72 73 url='http://hg.python-works.com',
73 74 install_requires=requirements,
74 75 classifiers=classifiers,
75 76 setup_requires=["PasteScript>=1.6.3"],
76 77 data_files=data_files,
77 78 packages=packages,
78 79 include_package_data=True,
79 80 test_suite='nose.collector',
80 81 package_data=package_data,
81 82 message_extractors={'rhodecode': [
82 83 ('**.py', 'python', None),
83 84 ('templates/**.mako', 'mako', {'input_encoding': 'utf-8'}),
84 85 ('public/**', 'ignore', None)]},
85 86 zip_safe=False,
86 87 paster_plugins=['PasteScript', 'Pylons'],
87 88 entry_points="""
88 89 [paste.app_factory]
89 90 main = rhodecode.config.middleware:make_app
90 91
91 92 [paste.app_install]
92 93 main = pylons.util:PylonsInstaller
93 94
94 95 [paste.global_paster_command]
95 96 make-index = rhodecode.lib.indexers:MakeIndex
96 97 upgrade-db = rhodecode.lib.dbmigrate:UpgradeDb
97 98 celeryd=rhodecode.lib.celerypylons.commands:CeleryDaemonCommand
98 99 celerybeat=rhodecode.lib.celerypylons.commands:CeleryBeatCommand
99 100 camqadm=rhodecode.lib.celerypylons.commands:CAMQPAdminCommand
100 101 celeryev=rhodecode.lib.celerypylons.commands:CeleryEventCommand
101 102
102 103 """,
103 104 )
General Comments 0
You need to be logged in to leave comments. Login now