##// END OF EJS Templates
Fixed archivals by passing baseui to scm get method for hg....
marcink -
r715:066af351 beta
parent child Browse files
Show More
@@ -1,230 +1,230 b''
1 .. _setup:
1 .. _setup:
2
2
3 Setup
3 Setup
4 =====
4 =====
5
5
6
6
7 Setting up the application
7 Setting up the application
8 --------------------------
8 --------------------------
9
9
10 ::
10 ::
11
11
12 paster make-config RhodeCode production.ini
12 paster make-config RhodeCode production.ini
13
13
14 - This will create `production.ini` config inside the directory
14 - This will create `production.ini` config inside the directory
15 this config contains various settings for rhodecode, e.g proxy port,
15 this config contains various settings for RhodeCode, e.g proxy port,
16 email settings,static files, cache and logging.
16 email settings,static files, cache and logging.
17
17
18 ::
18 ::
19
19
20 paster setup-app production.ini
20 paster setup-app production.ini
21
21
22 - This command will create all needed tables and an admin account.
22 - This command will create all needed tables and an admin account.
23 When asked for a path You can either use a new location of one with already
23 When asked for a path You can either use a new location of one with already
24 existing ones. RhodeCode will simply add all new found repositories to
24 existing ones. RhodeCode will simply add all new found repositories to
25 it's database. Also make sure You specify correct path to repositories.
25 it's database. Also make sure You specify correct path to repositories.
26 - Remember that the given path for mercurial_ repositories must be write
26 - Remember that the given path for mercurial_ repositories must be write
27 accessible for the application. It's very important since RhodeCode web interface
27 accessible for the application. It's very important since RhodeCode web interface
28 will work even without such an access but, when trying to do a push it'll
28 will work even without such an access but, when trying to do a push it'll
29 eventually fail with permission denied errors.
29 eventually fail with permission denied errors.
30 - Run
30 - Run
31
31
32 ::
32 ::
33
33
34 paster serve production.ini
34 paster serve production.ini
35
35
36 - This command runs the rhodecode server the app should be available at the
36 - This command runs the RhodeCode server the app should be available at the
37 127.0.0.1:5000. This ip and port is configurable via the production.ini
37 127.0.0.1:5000. This ip and port is configurable via the production.ini
38 file created in previous step
38 file created in previous step
39 - Use admin account you created to login.
39 - Use admin account you created to login.
40 - Default permissions on each repository is read, and owner is admin. So
40 - Default permissions on each repository is read, and owner is admin. So
41 remember to update these if needed.
41 remember to update these if needed.
42
42
43
43
44 Setting up Whoosh full text search
44 Setting up Whoosh full text search
45 ----------------------------------
45 ----------------------------------
46
46
47 Index for whoosh can be build starting from version 1.1 using paster command
47 Index for whoosh can be build starting from version 1.1 using paster command
48 passing repo locations to index, as well as Your config file that stores
48 passing repo locations to index, as well as Your config file that stores
49 whoosh index files locations. There is possible to pass `-f` to the options
49 whoosh index files locations. There is possible to pass `-f` to the options
50 to enable full index rebuild. Without that indexing will run always in in
50 to enable full index rebuild. Without that indexing will run always in in
51 incremental mode.
51 incremental mode.
52
52
53 ::
53 ::
54
54
55 paster make-index --repo-location=<location for repos> production.ini
55 paster make-index --repo-location=<location for repos> production.ini
56
56
57 for full index rebuild You can use
57 for full index rebuild You can use
58
58
59 ::
59 ::
60
60
61 paster make-index -f --repo-location=<location for repos> production.ini
61 paster make-index -f --repo-location=<location for repos> production.ini
62
62
63 - For full text search You can either put crontab entry for
63 - For full text search You can either put crontab entry for
64
64
65 This command can be run even from crontab in order to do periodical
65 This command can be run even from crontab in order to do periodical
66 index builds and keep Your index always up to date. An example entry might
66 index builds and keep Your index always up to date. An example entry might
67 look like this
67 look like this
68
68
69 ::
69 ::
70
70
71 /path/to/python/bin/paster --repo-location=<location for repos> /path/to/rhodecode/production.ini
71 /path/to/python/bin/paster --repo-location=<location for repos> /path/to/rhodecode/production.ini
72
72
73 When using incremental(default) mode whoosh will check last modification date
73 When using incremental(default) mode whoosh will check last modification date
74 of each file and add it to reindex if newer file is available. Also indexing
74 of each file and add it to reindex if newer file is available. Also indexing
75 daemon checks for removed files and removes them from index.
75 daemon checks for removed files and removes them from index.
76
76
77 Sometime You might want to rebuild index from scratch. You can do that using
77 Sometime You might want to rebuild index from scratch. You can do that using
78 the `-f` flag passed to paster command or, in admin panel You can check
78 the `-f` flag passed to paster command or, in admin panel You can check
79 `build from scratch` flag.
79 `build from scratch` flag.
80
80
81
81
82 Setting up LDAP support
82 Setting up LDAP support
83 -----------------------
83 -----------------------
84
84
85
85
86 RhodeCode starting from version 1.1 supports ldap authentication. In order
86 RhodeCode starting from version 1.1 supports ldap authentication. In order
87 to use ldap, You have to install ldap-python package. This package is available
87 to use ldap, You have to install ldap-python package. This package is available
88 via pypi, so You can install it by running
88 via pypi, so You can install it by running
89
89
90 ::
90 ::
91
91
92 easy_install ldap-python
92 easy_install ldap-python
93
93
94 ::
94 ::
95
95
96 pip install ldap-python
96 pip install ldap-python
97
97
98
98
99 ldap-python requires some certain libs on Your system, so before installing it
99 ldap-python requires some certain libs on Your system, so before installing it
100 check that You have at least `openldap`, and `sasl` libraries.
100 check that You have at least `openldap`, and `sasl` libraries.
101
101
102 ldap settings are located in admin->permissions section,
102 ldap settings are located in admin->permissions section,
103
103
104 Here's a typical ldap setup::
104 Here's a typical ldap setup::
105
105
106 Enable ldap = checked #controlls if ldap access is enabled
106 Enable ldap = checked #controlls if ldap access is enabled
107 Host = host.domain.org #acctuall ldap server to connect
107 Host = host.domain.org #acctuall ldap server to connect
108 Port = 389 or 689 for ldaps #ldap server ports
108 Port = 389 or 689 for ldaps #ldap server ports
109 Enable LDAPS = unchecked #enable disable ldaps
109 Enable LDAPS = unchecked #enable disable ldaps
110 Account = <account> #access for ldap server(if required)
110 Account = <account> #access for ldap server(if required)
111 Password = <password> #password for ldap server(if required)
111 Password = <password> #password for ldap server(if required)
112 Base DN = CN=users,DC=host,DC=domain,DC=org
112 Base DN = CN=users,DC=host,DC=domain,DC=org
113
113
114
114
115 `Account` and `Password` are optional, and used for two-phase ldap
115 `Account` and `Password` are optional, and used for two-phase ldap
116 authentication so those are credentials to access Your ldap, if it doesn't
116 authentication so those are credentials to access Your ldap, if it doesn't
117 support anonymous search/user lookups.
117 support anonymous search/user lookups.
118
118
119 If all data are entered correctly, and `ldap-python` is properly installed
119 If all data are entered correctly, and `ldap-python` is properly installed
120 Users should be granted to access rhodecode wit theire ldap accounts. When
120 Users should be granted to access RhodeCode wit theire ldap accounts. When
121 logging at the first time an special ldap account is created inside rhodecode,
121 logging at the first time an special ldap account is created inside RhodeCode,
122 so You can control over permissions even on ldap users. If such user exists
122 so You can control over permissions even on ldap users. If such user exists
123 already in rhodecode database ldap user with the same username would be not
123 already in RhodeCode database ldap user with the same username would be not
124 able to access rhodecode.
124 able to access RhodeCode.
125
125
126 If You have problems with ldap access and believe You entered correct
126 If You have problems with ldap access and believe You entered correct
127 information check out the rhodecode logs,any error messages sent from
127 information check out the RhodeCode logs,any error messages sent from
128 ldap will be saved there.
128 ldap will be saved there.
129
129
130
130
131 Nginx virtual host example
131 Nginx virtual host example
132 --------------------------
132 --------------------------
133
133
134 Sample config for nginx using proxy::
134 Sample config for nginx using proxy::
135
135
136 server {
136 server {
137 listen 80;
137 listen 80;
138 server_name hg.myserver.com;
138 server_name hg.myserver.com;
139 access_log /var/log/nginx/rhodecode.access.log;
139 access_log /var/log/nginx/rhodecode.access.log;
140 error_log /var/log/nginx/rhodecode.error.log;
140 error_log /var/log/nginx/rhodecode.error.log;
141 location / {
141 location / {
142 root /var/www/rhodecode/rhodecode/public/;
142 root /var/www/rhodecode/rhodecode/public/;
143 if (!-f $request_filename){
143 if (!-f $request_filename){
144 proxy_pass http://127.0.0.1:5000;
144 proxy_pass http://127.0.0.1:5000;
145 }
145 }
146 #this is important for https !!!
146 #this is important for https !!!
147 proxy_set_header X-Url-Scheme $scheme;
147 proxy_set_header X-Url-Scheme $scheme;
148 include /etc/nginx/proxy.conf;
148 include /etc/nginx/proxy.conf;
149 }
149 }
150 }
150 }
151
151
152 Here's the proxy.conf. It's tuned so it'll not timeout on long
152 Here's the proxy.conf. It's tuned so it'll not timeout on long
153 pushes and also on large pushes::
153 pushes and also on large pushes::
154
154
155 proxy_redirect off;
155 proxy_redirect off;
156 proxy_set_header Host $host;
156 proxy_set_header Host $host;
157 proxy_set_header X-Host $http_host;
157 proxy_set_header X-Host $http_host;
158 proxy_set_header X-Real-IP $remote_addr;
158 proxy_set_header X-Real-IP $remote_addr;
159 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
159 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
160 proxy_set_header Proxy-host $proxy_host;
160 proxy_set_header Proxy-host $proxy_host;
161 client_max_body_size 400m;
161 client_max_body_size 400m;
162 client_body_buffer_size 128k;
162 client_body_buffer_size 128k;
163 proxy_buffering off;
163 proxy_buffering off;
164 proxy_connect_timeout 3600;
164 proxy_connect_timeout 3600;
165 proxy_send_timeout 3600;
165 proxy_send_timeout 3600;
166 proxy_read_timeout 3600;
166 proxy_read_timeout 3600;
167 proxy_buffer_size 8k;
167 proxy_buffer_size 8k;
168 proxy_buffers 8 32k;
168 proxy_buffers 8 32k;
169 proxy_busy_buffers_size 64k;
169 proxy_busy_buffers_size 64k;
170 proxy_temp_file_write_size 64k;
170 proxy_temp_file_write_size 64k;
171
171
172 Also when using root path with nginx You might set the static files to false
172 Also when using root path with nginx You might set the static files to false
173 in production.ini file::
173 in production.ini file::
174
174
175 [app:main]
175 [app:main]
176 use = egg:rhodecode
176 use = egg:rhodecode
177 full_stack = true
177 full_stack = true
178 static_files = false
178 static_files = false
179 lang=en
179 lang=en
180 cache_dir = %(here)s/data
180 cache_dir = %(here)s/data
181
181
182 To not have the statics served by the application. And improve speed.
182 To not have the statics served by the application. And improve speed.
183
183
184
184
185
185
186 Apache's example FCGI config
186 Apache's example FCGI config
187 ----------------------------
187 ----------------------------
188
188
189 TODO !
189 TODO !
190
190
191 Other configuration files
191 Other configuration files
192 -------------------------
192 -------------------------
193
193
194 Some extra configuration files and examples can be found here:
194 Some extra configuration files and examples can be found here:
195 http://hg.python-works.com/rhodecode/files/tip/init.d
195 http://hg.python-works.com/rhodecode/files/tip/init.d
196
196
197 and also an celeryconfig file can be use from here:
197 and also an celeryconfig file can be use from here:
198 http://hg.python-works.com/rhodecode/files/tip/celeryconfig.py
198 http://hg.python-works.com/rhodecode/files/tip/celeryconfig.py
199
199
200 Troubleshooting
200 Troubleshooting
201 ---------------
201 ---------------
202
202
203 - missing static files ?
203 - missing static files ?
204
204
205 - make sure either to set the `static_files = true` in the .ini file or
205 - make sure either to set the `static_files = true` in the .ini file or
206 double check the root path for Your http setup. It should point to
206 double check the root path for Your http setup. It should point to
207 for example:
207 for example:
208 /home/my-virtual-python/lib/python2.6/site-packages/rhodecode/public
208 /home/my-virtual-python/lib/python2.6/site-packages/rhodecode/public
209
209
210 - can't install celery/rabbitmq
210 - can't install celery/rabbitmq
211
211
212 - don't worry RhodeCode works without them too. No extra setup required
212 - don't worry RhodeCode works without them too. No extra setup required
213
213
214
214
215 - long lasting push timeouts ?
215 - long lasting push timeouts ?
216
216
217 - make sure You set a longer timeouts in Your proxy/fcgi settings, timeouts
217 - make sure You set a longer timeouts in Your proxy/fcgi settings, timeouts
218 are caused by https server and not rhodecode
218 are caused by https server and not RhodeCode
219
219
220 - large pushes timeouts ?
220 - large pushes timeouts ?
221
221
222 - make sure You set a proper max_body_size for the http server
222 - make sure You set a proper max_body_size for the http server
223
223
224
224
225
225
226 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
226 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
227 .. _python: http://www.python.org/
227 .. _python: http://www.python.org/
228 .. _mercurial: http://mercurial.selenic.com/
228 .. _mercurial: http://mercurial.selenic.com/
229 .. _celery: http://celeryproject.org/
229 .. _celery: http://celeryproject.org/
230 .. _rabbitmq: http://www.rabbitmq.com/ No newline at end of file
230 .. _rabbitmq: http://www.rabbitmq.com/
@@ -1,242 +1,243 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # Model for RhodeCode
3 # Model for RhodeCode
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 9, 2010
21 Created on April 9, 2010
22 Model for RhodeCode
22 Model for RhodeCode
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from beaker.cache import cache_region, region_invalidate
25 from beaker.cache import cache_region, region_invalidate
26 from mercurial import ui
26 from mercurial import ui
27 from rhodecode import BACKENDS
27 from rhodecode import BACKENDS
28 from rhodecode.lib import helpers as h
28 from rhodecode.lib import helpers as h
29 from rhodecode.lib.auth import HasRepoPermissionAny
29 from rhodecode.lib.auth import HasRepoPermissionAny
30 from rhodecode.lib.utils import get_repos
30 from rhodecode.lib.utils import get_repos
31 from rhodecode.model import meta
31 from rhodecode.model import meta
32 from rhodecode.model.db import Repository, User, RhodeCodeUi, CacheInvalidation
32 from rhodecode.model.db import Repository, User, RhodeCodeUi, CacheInvalidation
33 from rhodecode.model.caching_query import FromCache
33 from rhodecode.model.caching_query import FromCache
34 from sqlalchemy.orm import joinedload
34 from sqlalchemy.orm import joinedload
35 from sqlalchemy.orm.session import make_transient
35 from sqlalchemy.orm.session import make_transient
36 from vcs import get_backend
36 from vcs import get_backend
37 from vcs.utils.helpers import get_scm
37 from vcs.utils.helpers import get_scm
38 from vcs.exceptions import RepositoryError, VCSError
38 from vcs.exceptions import RepositoryError, VCSError
39 from vcs.utils.lazy import LazyProperty
39 from vcs.utils.lazy import LazyProperty
40 import traceback
40 import traceback
41 import logging
41 import logging
42 import os
42 import os
43 import time
43 import time
44
44
45 log = logging.getLogger(__name__)
45 log = logging.getLogger(__name__)
46
46
47 class ScmModel(object):
47 class ScmModel(object):
48 """
48 """
49 Mercurial Model
49 Mercurial Model
50 """
50 """
51
51
52 def __init__(self):
52 def __init__(self):
53 self.sa = meta.Session()
53 self.sa = meta.Session()
54
54
55 @LazyProperty
55 @LazyProperty
56 def repos_path(self):
56 def repos_path(self):
57 """
57 """
58 Get's the repositories root path from database
58 Get's the repositories root path from database
59 """
59 """
60 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
60 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
61
61
62 return q.ui_value
62 return q.ui_value
63
63
64 def repo_scan(self, repos_path, baseui, initial=False):
64 def repo_scan(self, repos_path, baseui, initial=False):
65 """
65 """
66 Listing of repositories in given path. This path should not be a
66 Listing of repositories in given path. This path should not be a
67 repository itself. Return a dictionary of repository objects
67 repository itself. Return a dictionary of repository objects
68
68
69 :param repos_path: path to directory containing repositories
69 :param repos_path: path to directory containing repositories
70 :param baseui
70 :param baseui
71 :param initial: initial scan
71 :param initial: initial scan
72 """
72 """
73 log.info('scanning for repositories in %s', repos_path)
73 log.info('scanning for repositories in %s', repos_path)
74
74
75 if not isinstance(baseui, ui.ui):
75 if not isinstance(baseui, ui.ui):
76 baseui = ui.ui()
76 baseui = ui.ui()
77 repos_list = {}
77 repos_list = {}
78
78
79 for name, path in get_repos(repos_path):
79 for name, path in get_repos(repos_path):
80 try:
80 try:
81 if repos_list.has_key(name):
81 if repos_list.has_key(name):
82 raise RepositoryError('Duplicate repository name %s '
82 raise RepositoryError('Duplicate repository name %s '
83 'found in %s' % (name, path))
83 'found in %s' % (name, path))
84 else:
84 else:
85
85
86 klass = get_backend(path[0])
86 klass = get_backend(path[0])
87
87
88 if path[0] == 'hg' and path[0] in BACKENDS.keys():
88 if path[0] == 'hg' and path[0] in BACKENDS.keys():
89 repos_list[name] = klass(path[1], baseui=baseui)
89 repos_list[name] = klass(path[1], baseui=baseui)
90
90
91 if path[0] == 'git' and path[0] in BACKENDS.keys():
91 if path[0] == 'git' and path[0] in BACKENDS.keys():
92 repos_list[name] = klass(path[1])
92 repos_list[name] = klass(path[1])
93 except OSError:
93 except OSError:
94 continue
94 continue
95
95
96 return repos_list
96 return repos_list
97
97
98 def get_repos(self, all_repos=None):
98 def get_repos(self, all_repos=None):
99 """
99 """
100 Get all repos from db and for each repo create it's backend instance.
100 Get all repos from db and for each repo create it's backend instance.
101 and fill that backed with information from database
101 and fill that backed with information from database
102
102
103 :param all_repos: give specific repositories list, good for filtering
103 :param all_repos: give specific repositories list, good for filtering
104 """
104 """
105 if not all_repos:
105 if not all_repos:
106 all_repos = self.sa.query(Repository)\
106 all_repos = self.sa.query(Repository)\
107 .order_by(Repository.repo_name).all()
107 .order_by(Repository.repo_name).all()
108
108
109 for r in all_repos:
109 for r in all_repos:
110
110
111 repo = self.get(r.repo_name)
111 repo = self.get(r.repo_name)
112
112
113 if repo is not None:
113 if repo is not None:
114 last_change = repo.last_change
114 last_change = repo.last_change
115 tip = h.get_changeset_safe(repo, 'tip')
115 tip = h.get_changeset_safe(repo, 'tip')
116
116
117 tmp_d = {}
117 tmp_d = {}
118 tmp_d['name'] = repo.name
118 tmp_d['name'] = repo.name
119 tmp_d['name_sort'] = tmp_d['name'].lower()
119 tmp_d['name_sort'] = tmp_d['name'].lower()
120 tmp_d['description'] = repo.dbrepo.description
120 tmp_d['description'] = repo.dbrepo.description
121 tmp_d['description_sort'] = tmp_d['description']
121 tmp_d['description_sort'] = tmp_d['description']
122 tmp_d['last_change'] = last_change
122 tmp_d['last_change'] = last_change
123 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
123 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
124 tmp_d['tip'] = tip.raw_id
124 tmp_d['tip'] = tip.raw_id
125 tmp_d['tip_sort'] = tip.revision
125 tmp_d['tip_sort'] = tip.revision
126 tmp_d['rev'] = tip.revision
126 tmp_d['rev'] = tip.revision
127 tmp_d['contact'] = repo.dbrepo.user.full_contact
127 tmp_d['contact'] = repo.dbrepo.user.full_contact
128 tmp_d['contact_sort'] = tmp_d['contact']
128 tmp_d['contact_sort'] = tmp_d['contact']
129 tmp_d['repo_archives'] = list(repo._get_archives())
129 tmp_d['repo_archives'] = list(repo._get_archives())
130 tmp_d['last_msg'] = tip.message
130 tmp_d['last_msg'] = tip.message
131 tmp_d['repo'] = repo
131 tmp_d['repo'] = repo
132 yield tmp_d
132 yield tmp_d
133
133
134 def get_repo(self, repo_name):
134 def get_repo(self, repo_name):
135 return self.get(repo_name)
135 return self.get(repo_name)
136
136
137 def get(self, repo_name):
137 def get(self, repo_name):
138 """
138 """
139 Get's repository from given name, creates BackendInstance and
139 Get's repository from given name, creates BackendInstance and
140 propagates it's data from database with all additional information
140 propagates it's data from database with all additional information
141 :param repo_name:
141 :param repo_name:
142 """
142 """
143 if not HasRepoPermissionAny('repository.read', 'repository.write',
143 if not HasRepoPermissionAny('repository.read', 'repository.write',
144 'repository.admin')(repo_name, 'get repo check'):
144 'repository.admin')(repo_name, 'get repo check'):
145 return
145 return
146
146
147 @cache_region('long_term')
147 @cache_region('long_term')
148 def _get_repo(repo_name):
148 def _get_repo(repo_name):
149
149
150 repo_path = os.path.join(self.repos_path, repo_name)
150 repo_path = os.path.join(self.repos_path, repo_name)
151 alias = get_scm(repo_path)[0]
151 alias = get_scm(repo_path)[0]
152
152
153 log.debug('Creating instance of %s repository', alias)
153 log.debug('Creating instance of %s repository', alias)
154 backend = get_backend(alias)
154 backend = get_backend(alias)
155
155
156 #TODO: get the baseui from somewhere for this
156 #TODO: get the baseui from somewhere for this
157 if alias == 'hg':
157 if alias == 'hg':
158 repo = backend(repo_path, create=False, baseui=None)
158 from pylons import app_globals as g
159 repo = backend(repo_path, create=False, baseui=g.baseui)
159 #skip hidden web repository
160 #skip hidden web repository
160 if repo._get_hidden():
161 if repo._get_hidden():
161 return
162 return
162 else:
163 else:
163 repo = backend(repo_path, create=False)
164 repo = backend(repo_path, create=False)
164
165
165 dbrepo = self.sa.query(Repository)\
166 dbrepo = self.sa.query(Repository)\
166 .options(joinedload(Repository.fork))\
167 .options(joinedload(Repository.fork))\
167 .options(joinedload(Repository.user))\
168 .options(joinedload(Repository.user))\
168 .filter(Repository.repo_name == repo_name)\
169 .filter(Repository.repo_name == repo_name)\
169 .scalar()
170 .scalar()
170 make_transient(dbrepo)
171 make_transient(dbrepo)
171 repo.dbrepo = dbrepo
172 repo.dbrepo = dbrepo
172 return repo
173 return repo
173
174
174 invalidate = self._should_invalidate(repo_name)
175 invalidate = self._should_invalidate(repo_name)
175 if invalidate:
176 if invalidate:
176 log.info('invalidating cache for repository %s', repo_name)
177 log.info('invalidating cache for repository %s', repo_name)
177 region_invalidate(_get_repo, None, repo_name)
178 region_invalidate(_get_repo, None, repo_name)
178 self._mark_invalidated(invalidate)
179 self._mark_invalidated(invalidate)
179
180
180 return _get_repo(repo_name)
181 return _get_repo(repo_name)
181
182
182
183
183
184
184 def mark_for_invalidation(self, repo_name):
185 def mark_for_invalidation(self, repo_name):
185 """
186 """
186 Puts cache invalidation task into db for
187 Puts cache invalidation task into db for
187 further global cache invalidation
188 further global cache invalidation
188
189
189 :param repo_name: this repo that should invalidation take place
190 :param repo_name: this repo that should invalidation take place
190 """
191 """
191 log.debug('marking %s for invalidation', repo_name)
192 log.debug('marking %s for invalidation', repo_name)
192 cache = self.sa.query(CacheInvalidation)\
193 cache = self.sa.query(CacheInvalidation)\
193 .filter(CacheInvalidation.cache_key == repo_name).scalar()
194 .filter(CacheInvalidation.cache_key == repo_name).scalar()
194
195
195 if cache:
196 if cache:
196 #mark this cache as inactive
197 #mark this cache as inactive
197 cache.cache_active = False
198 cache.cache_active = False
198 else:
199 else:
199 log.debug('cache key not found in invalidation db -> creating one')
200 log.debug('cache key not found in invalidation db -> creating one')
200 cache = CacheInvalidation(repo_name)
201 cache = CacheInvalidation(repo_name)
201
202
202 try:
203 try:
203 self.sa.add(cache)
204 self.sa.add(cache)
204 self.sa.commit()
205 self.sa.commit()
205 except:
206 except:
206 log.error(traceback.format_exc())
207 log.error(traceback.format_exc())
207 self.sa.rollback()
208 self.sa.rollback()
208
209
209
210
210
211
211
212
212
213
213 def _should_invalidate(self, repo_name):
214 def _should_invalidate(self, repo_name):
214 """
215 """
215 Looks up database for invalidation signals for this repo_name
216 Looks up database for invalidation signals for this repo_name
216 :param repo_name:
217 :param repo_name:
217 """
218 """
218
219
219 ret = self.sa.query(CacheInvalidation)\
220 ret = self.sa.query(CacheInvalidation)\
220 .options(FromCache('sql_cache_short',
221 .options(FromCache('sql_cache_short',
221 'get_invalidation_%s' % repo_name))\
222 'get_invalidation_%s' % repo_name))\
222 .filter(CacheInvalidation.cache_key == repo_name)\
223 .filter(CacheInvalidation.cache_key == repo_name)\
223 .filter(CacheInvalidation.cache_active == False)\
224 .filter(CacheInvalidation.cache_active == False)\
224 .scalar()
225 .scalar()
225
226
226 return ret
227 return ret
227
228
228 def _mark_invalidated(self, cache_key):
229 def _mark_invalidated(self, cache_key):
229 """
230 """
230 Marks all occurences of cache to invaldation as already invalidated
231 Marks all occurences of cache to invaldation as already invalidated
231 @param repo_name:
232 @param repo_name:
232 """
233 """
233 if cache_key:
234 if cache_key:
234 log.debug('marking %s as already invalidated', cache_key)
235 log.debug('marking %s as already invalidated', cache_key)
235 try:
236 try:
236 cache_key.cache_active = True
237 cache_key.cache_active = True
237 self.sa.add(cache_key)
238 self.sa.add(cache_key)
238 self.sa.commit()
239 self.sa.commit()
239 except:
240 except:
240 log.error(traceback.format_exc())
241 log.error(traceback.format_exc())
241 self.sa.rollback()
242 self.sa.rollback()
242
243
General Comments 0
You need to be logged in to leave comments. Login now