##// END OF EJS Templates
Added universal cache invalidator for two cached functions....
marcink -
r171:52bbeb1e default
parent child Browse files
Show More
@@ -1,101 +1,101 b''
1 import logging
1 import logging
2 import os
2 import os
3
3
4 from pylons import request, response, session, tmpl_context as c, url, app_globals as g
4 from pylons import request, response, session, tmpl_context as c, url, app_globals as g
5 from pylons.controllers.util import abort, redirect
5 from pylons.controllers.util import abort, redirect
6 from pylons_app.lib.base import BaseController, render
6 from pylons_app.lib.base import BaseController, render
7 from pylons_app.lib import auth
7 from pylons_app.lib import auth
8 from pylons_app.model.forms import LoginForm
8 from pylons_app.model.forms import LoginForm
9 import formencode
9 import formencode
10 import formencode.htmlfill as htmlfill
10 import formencode.htmlfill as htmlfill
11 from pylons_app.model import meta
11 from pylons_app.model import meta
12 from pylons_app.model.db import Users, UserLogs
12 from pylons_app.model.db import Users, UserLogs
13 from webhelpers.paginate import Page
13 from webhelpers.paginate import Page
14 from pylons_app.lib.utils import check_repo, invalidate_cache
14 from pylons_app.lib.utils import check_repo, invalidate_cache
15
15
16 log = logging.getLogger(__name__)
16 log = logging.getLogger(__name__)
17
17
18 class AdminController(BaseController):
18 class AdminController(BaseController):
19
19
20 def __before__(self):
20 def __before__(self):
21 c.admin_user = session.get('admin_user', False)
21 c.admin_user = session.get('admin_user', False)
22 c.admin_username = session.get('admin_username')
22 c.admin_username = session.get('admin_username')
23
23
24 def index(self):
24 def index(self):
25 # Return a rendered template
25 # Return a rendered template
26 if request.POST:
26 if request.POST:
27 #import Login Form validator class
27 #import Login Form validator class
28 login_form = LoginForm()
28 login_form = LoginForm()
29
29
30 try:
30 try:
31 c.form_result = login_form.to_python(dict(request.params))
31 c.form_result = login_form.to_python(dict(request.params))
32 if auth.admin_auth(c.form_result['username'], c.form_result['password']):
32 if auth.admin_auth(c.form_result['username'], c.form_result['password']):
33 session['admin_user'] = True
33 session['admin_user'] = True
34 session['admin_username'] = c.form_result['username']
34 session['admin_username'] = c.form_result['username']
35 session.save()
35 session.save()
36 return redirect(url('admin_home'))
36 return redirect(url('admin_home'))
37 else:
37 else:
38 raise formencode.Invalid('Login Error', None, None,
38 raise formencode.Invalid('Login Error', None, None,
39 error_dict={'username':'invalid login',
39 error_dict={'username':'invalid login',
40 'password':'invalid password'})
40 'password':'invalid password'})
41
41
42 except formencode.Invalid, error:
42 except formencode.Invalid, error:
43 c.form_result = error.value
43 c.form_result = error.value
44 c.form_errors = error.error_dict or {}
44 c.form_errors = error.error_dict or {}
45 html = render('admin/admin.html')
45 html = render('admin/admin.html')
46
46
47 return htmlfill.render(
47 return htmlfill.render(
48 html,
48 html,
49 defaults=c.form_result,
49 defaults=c.form_result,
50 encoding="UTF-8"
50 encoding="UTF-8"
51 )
51 )
52 if c.admin_user:
52 if c.admin_user:
53 sa = meta.Session
53 sa = meta.Session
54
54
55 users_log = sa.query(UserLogs)\
55 users_log = sa.query(UserLogs)\
56 .order_by(UserLogs.action_date.desc())
56 .order_by(UserLogs.action_date.desc())
57 p = int(request.params.get('page', 1))
57 p = int(request.params.get('page', 1))
58 c.users_log = Page(users_log, page=p, items_per_page=10)
58 c.users_log = Page(users_log, page=p, items_per_page=10)
59 c.log_data = render('admin/admin_log.html')
59 c.log_data = render('admin/admin_log.html')
60 if request.params.get('partial'):
60 if request.params.get('partial'):
61 return c.log_data
61 return c.log_data
62 return render('admin/admin.html')
62 return render('admin/admin.html')
63
63
64 def hgrc(self, dirname):
64 def hgrc(self, dirname):
65 filename = os.path.join(dirname, '.hg', 'hgrc')
65 filename = os.path.join(dirname, '.hg', 'hgrc')
66 return filename
66 return filename
67
67
68 def add_repo(self, new_repo):
68 def add_repo(self, new_repo):
69
69
70
70
71 #extra check it can be add since it's the command
71 #extra check it can be add since it's the command
72 if new_repo == '_admin':
72 if new_repo == '_admin':
73 c.msg = 'DENIED'
73 c.msg = 'DENIED'
74 c.new_repo = ''
74 c.new_repo = ''
75 return render('admin/add.html')
75 return render('admin/add.html')
76
76
77 new_repo = new_repo.replace(" ", "_")
77 new_repo = new_repo.replace(" ", "_")
78 new_repo = new_repo.replace("-", "_")
78 new_repo = new_repo.replace("-", "_")
79
79
80 try:
80 try:
81 self._create_repo(new_repo)
81 self._create_repo(new_repo)
82 c.new_repo = new_repo
82 c.new_repo = new_repo
83 c.msg = 'added repo'
83 c.msg = 'added repo'
84 #clear our cached list for refresh with new repo
84 #clear our cached list for refresh with new repo
85 invalidate_cache('repo_list_2')
85 invalidate_cache('cached_repo_list')
86 except Exception as e:
86 except Exception as e:
87 c.new_repo = 'Exception when adding: %s' % new_repo
87 c.new_repo = 'Exception when adding: %s' % new_repo
88 c.msg = str(e)
88 c.msg = str(e)
89
89
90 return render('admin/add.html')
90 return render('admin/add.html')
91
91
92
92
93 def _create_repo(self, repo_name):
93 def _create_repo(self, repo_name):
94 if repo_name in [None, '', 'add']:
94 if repo_name in [None, '', 'add']:
95 raise Exception('undefined repo_name of repo')
95 raise Exception('undefined repo_name of repo')
96 repo_path = os.path.join(g.base_path, repo_name)
96 repo_path = os.path.join(g.base_path, repo_name)
97 if check_repo(repo_name, g.base_path):
97 if check_repo(repo_name, g.base_path):
98 log.info('creating repo %s in %s', repo_name, repo_path)
98 log.info('creating repo %s in %s', repo_name, repo_path)
99 from vcs.backends.hg import MercurialRepository
99 from vcs.backends.hg import MercurialRepository
100 MercurialRepository(repo_path, create=True)
100 MercurialRepository(repo_path, create=True)
101
101
@@ -1,59 +1,64 b''
1 import os
1 import os
2 from mercurial.hgweb import hgweb
2 from mercurial.hgweb import hgweb
3 from mercurial.hgweb.request import wsgiapplication
3 from mercurial.hgweb.request import wsgiapplication
4 from pylons_app.lib.utils import make_ui
4 from pylons_app.lib.utils import make_ui, invalidate_cache
5 from pylons.controllers.util import abort
5 from pylons.controllers.util import abort
6 from webob.exc import HTTPNotFound
6 from webob.exc import HTTPNotFound
7 class SimpleHg(object):
7 class SimpleHg(object):
8
8
9 def __init__(self, application, config):
9 def __init__(self, application, config):
10 self.application = application
10 self.application = application
11 self.config = config
11 self.config = config
12
12
13 def __call__(self, environ, start_response):
13 def __call__(self, environ, start_response):
14 if not is_mercurial(environ):
14 if not is_mercurial(environ):
15 return self.application(environ, start_response)
15 return self.application(environ, start_response)
16 else:
16 else:
17 try:
17 try:
18 repo_name = environ['PATH_INFO'].split('/')[1]
18 repo_name = environ['PATH_INFO'].split('/')[1]
19 except:
19 except:
20 return HTTPNotFound()(environ, start_response)
20 return HTTPNotFound()(environ, start_response)
21
21
22 #since we wrap into hgweb, just reset the path
22 #since we wrap into hgweb, just reset the path
23 environ['PATH_INFO'] = '/'
23 environ['PATH_INFO'] = '/'
24 self.baseui = make_ui()
24 self.baseui = make_ui()
25 self.basepath = self.baseui.configitems('paths')[0][1].replace('*', '')
25 self.basepath = self.baseui.configitems('paths')[0][1]\
26 .replace('*', '')
26 self.repo_path = os.path.join(self.basepath, repo_name)
27 self.repo_path = os.path.join(self.basepath, repo_name)
27 try:
28 try:
28 app = wsgiapplication(self._make_app)
29 app = wsgiapplication(self._make_app)
29 except Exception as e:
30 except Exception as e:
30 return HTTPNotFound()(environ, start_response)
31 return HTTPNotFound()(environ, start_response)
32
33 """we know that some change was made to repositories and we should
34 invalidate the cache to see the changes right away"""
35 invalidate_cache('full_changelog', repo_name)
31 return app(environ, start_response)
36 return app(environ, start_response)
32
37
33 def _make_app(self):
38 def _make_app(self):
34 hgserve = hgweb(self.repo_path)
39 hgserve = hgweb(self.repo_path)
35 return self.load_web_settings(hgserve)
40 return self.load_web_settings(hgserve)
36
41
37
42
38 def load_web_settings(self, hgserve):
43 def load_web_settings(self, hgserve):
39 repoui = make_ui(os.path.join(self.repo_path, '.hg', 'hgrc'), False)
44 repoui = make_ui(os.path.join(self.repo_path, '.hg', 'hgrc'), False)
40 #set the global ui for hgserve
45 #set the global ui for hgserve
41 hgserve.repo.ui = self.baseui
46 hgserve.repo.ui = self.baseui
42
47
43 if repoui:
48 if repoui:
44 #set the repository based config
49 #set the repository based config
45 hgserve.repo.ui = repoui
50 hgserve.repo.ui = repoui
46
51
47 return hgserve
52 return hgserve
48
53
49 def is_mercurial(environ):
54 def is_mercurial(environ):
50 """
55 """
51 Returns True if request's target is mercurial server - header
56 Returns True if request's target is mercurial server - header
52 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
57 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
53 """
58 """
54 http_accept = environ.get('HTTP_ACCEPT')
59 http_accept = environ.get('HTTP_ACCEPT')
55 if http_accept and http_accept.startswith('application/mercurial'):
60 if http_accept and http_accept.startswith('application/mercurial'):
56 return True
61 return True
57 return False
62 return False
58
63
59
64
@@ -1,114 +1,125 b''
1 import os
1 import os
2 import logging
2 import logging
3 from mercurial import ui, config, hg
3 from mercurial import ui, config, hg
4 from mercurial.error import RepoError
4 from mercurial.error import RepoError
5 log = logging.getLogger(__name__)
5 log = logging.getLogger(__name__)
6
6
7
7
8 def get_repo_slug(request):
8 def get_repo_slug(request):
9 path_info = request.environ.get('PATH_INFO')
9 path_info = request.environ.get('PATH_INFO')
10 uri_lst = path_info.split('/')
10 uri_lst = path_info.split('/')
11 repo_name = uri_lst[1]
11 repo_name = uri_lst[1]
12 return repo_name
12 return repo_name
13
13
14 def is_mercurial(environ):
14 def is_mercurial(environ):
15 """
15 """
16 Returns True if request's target is mercurial server - header
16 Returns True if request's target is mercurial server - header
17 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
17 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
18 """
18 """
19 http_accept = environ.get('HTTP_ACCEPT')
19 http_accept = environ.get('HTTP_ACCEPT')
20 if http_accept and http_accept.startswith('application/mercurial'):
20 if http_accept and http_accept.startswith('application/mercurial'):
21 return True
21 return True
22 return False
22 return False
23
23
24 def check_repo_dir(paths):
24 def check_repo_dir(paths):
25 repos_path = paths[0][1].split('/')
25 repos_path = paths[0][1].split('/')
26 if repos_path[-1] in ['*', '**']:
26 if repos_path[-1] in ['*', '**']:
27 repos_path = repos_path[:-1]
27 repos_path = repos_path[:-1]
28 if repos_path[0] != '/':
28 if repos_path[0] != '/':
29 repos_path[0] = '/'
29 repos_path[0] = '/'
30 if not os.path.isdir(os.path.join(*repos_path)):
30 if not os.path.isdir(os.path.join(*repos_path)):
31 raise Exception('Not a valid repository in %s' % paths[0][1])
31 raise Exception('Not a valid repository in %s' % paths[0][1])
32
32
33 def check_repo(repo_name, base_path):
33 def check_repo(repo_name, base_path):
34
34
35 repo_path = os.path.join(base_path, repo_name)
35 repo_path = os.path.join(base_path, repo_name)
36
36
37 try:
37 try:
38 r = hg.repository(ui.ui(), repo_path)
38 r = hg.repository(ui.ui(), repo_path)
39 hg.verify(r)
39 hg.verify(r)
40 #here we hnow that repo exists it was verified
40 #here we hnow that repo exists it was verified
41 log.info('%s repo is already created', repo_name)
41 log.info('%s repo is already created', repo_name)
42 return False
42 return False
43 #raise Exception('Repo exists')
43 #raise Exception('Repo exists')
44 except RepoError:
44 except RepoError:
45 log.info('%s repo is free for creation', repo_name)
45 log.info('%s repo is free for creation', repo_name)
46 #it means that there is no valid repo there...
46 #it means that there is no valid repo there...
47 return True
47 return True
48
48
49 def make_ui(path='hgwebdir.config', checkpaths=True):
49 def make_ui(path='hgwebdir.config', checkpaths=True):
50 """
50 """
51 A funcion that will read python rc files and make an ui from read options
51 A funcion that will read python rc files and make an ui from read options
52
52
53 @param path: path to mercurial config file
53 @param path: path to mercurial config file
54 """
54 """
55 if not os.path.isfile(path):
55 if not os.path.isfile(path):
56 log.error('Unable to read config file %s' % path)
56 log.error('Unable to read config file %s' % path)
57 return False
57 return False
58 #propagated from mercurial documentation
58 #propagated from mercurial documentation
59 sections = [
59 sections = [
60 'alias',
60 'alias',
61 'auth',
61 'auth',
62 'decode/encode',
62 'decode/encode',
63 'defaults',
63 'defaults',
64 'diff',
64 'diff',
65 'email',
65 'email',
66 'extensions',
66 'extensions',
67 'format',
67 'format',
68 'merge-patterns',
68 'merge-patterns',
69 'merge-tools',
69 'merge-tools',
70 'hooks',
70 'hooks',
71 'http_proxy',
71 'http_proxy',
72 'smtp',
72 'smtp',
73 'patch',
73 'patch',
74 'paths',
74 'paths',
75 'profiling',
75 'profiling',
76 'server',
76 'server',
77 'trusted',
77 'trusted',
78 'ui',
78 'ui',
79 'web',
79 'web',
80 ]
80 ]
81
81
82 baseui = ui.ui()
82 baseui = ui.ui()
83 cfg = config.config()
83 cfg = config.config()
84 cfg.read(path)
84 cfg.read(path)
85 if checkpaths:check_repo_dir(cfg.items('paths'))
85 if checkpaths:check_repo_dir(cfg.items('paths'))
86
86
87 for section in sections:
87 for section in sections:
88 for k, v in cfg.items(section):
88 for k, v in cfg.items(section):
89 baseui.setconfig(section, k, v)
89 baseui.setconfig(section, k, v)
90
90
91 return baseui
91 return baseui
92
92
93 def invalidate_cache(name):
93 def invalidate_cache(name, *args):
94 from beaker.cache import region_invalidate
94 from beaker.cache import region_invalidate
95 if name == 'repo_list_2':
95 log.info('INVALIDATING CACHE FOR %s', name)
96 log.info('INVALIDATING CACHE FOR %s', name)
96
97 from pylons_app.lib.base import _get_repos
97 """propaget our arguments to make sure invalidation works. First
98 #clear our cached list for refresh with new repo
98 argument has to be the name of cached func name give to cache decorator
99 region_invalidate(_get_repos, None, 'repo_list_2')
99 without that the invalidation would not work"""
100
100 tmp = [name]
101 tmp.extend(args)
102 args = tuple(tmp)
103
104 if name == 'cached_repo_list':
105 from pylons_app.lib.base import _get_repos_cached
106 region_invalidate(_get_repos_cached, None, *args)
107
108 if name == 'full_changelog':
109 from pylons_app.controllers.changelog import _full_changelog_cached
110 region_invalidate(_full_changelog_cached, None, *args)
111
101 from vcs.backends.base import BaseChangeset
112 from vcs.backends.base import BaseChangeset
102 from vcs.utils.lazy import LazyProperty
113 from vcs.utils.lazy import LazyProperty
103 class EmptyChangeset(BaseChangeset):
114 class EmptyChangeset(BaseChangeset):
104
115
105 revision = -1
116 revision = -1
106
117
107 @LazyProperty
118 @LazyProperty
108 def raw_id(self):
119 def raw_id(self):
109 """
120 """
110 Returns raw string identifing this changeset, useful for web
121 Returns raw string identifing this changeset, useful for web
111 representation.
122 representation.
112 """
123 """
113 return '0' * 12
124 return '0' * 12
114
125
General Comments 0
You need to be logged in to leave comments. Login now