##// END OF EJS Templates
moved cache invalidating to utils, as seperate function. Implemented invalidating in
marcink -
r140:b5e59e2b default
parent child Browse files
Show More
@@ -1,102 +1,101
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 beaker.cache import region_invalidate
7 from pylons_app.lib.base import BaseController, render
6 from pylons_app.lib.base import BaseController, render
8 from pylons_app.lib import auth
7 from pylons_app.lib import auth
9 from pylons_app.model.forms import LoginForm
8 from pylons_app.model.forms import LoginForm
10 import formencode
9 import formencode
11 import formencode.htmlfill as htmlfill
10 import formencode.htmlfill as htmlfill
12 from pylons_app.model import meta
11 from pylons_app.model import meta
13 from pylons_app.model.db import Users, UserLogs
12 from pylons_app.model.db import Users, UserLogs
14 from webhelpers.paginate import Page
13 from webhelpers.paginate import Page
15 from pylons_app.lib.utils import check_repo
14 from pylons_app.lib.utils import check_repo, invalidate_cache
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 from pylons_app.lib.base import _get_repos
85 #clear our cached list for refresh with new repo
84 #clear our cached list for refresh with new repo
86 region_invalidate(_get_repos, None, 'repo_list_2')
85 invalidate_cache('repo_list_2')
87 except Exception as e:
86 except Exception as e:
88 c.new_repo = 'Exception when adding: %s' % new_repo
87 c.new_repo = 'Exception when adding: %s' % new_repo
89 c.msg = str(e)
88 c.msg = str(e)
90
89
91 return render('admin/add.html')
90 return render('admin/add.html')
92
91
93
92
94 def _create_repo(self, repo_name):
93 def _create_repo(self, repo_name):
95 if repo_name in [None, '', 'add']:
94 if repo_name in [None, '', 'add']:
96 raise Exception('undefined repo_name of repo')
95 raise Exception('undefined repo_name of repo')
97 repo_path = os.path.join(g.base_path, repo_name)
96 repo_path = os.path.join(g.base_path, repo_name)
98 if check_repo(repo_name, g.base_path):
97 if check_repo(repo_name, g.base_path):
99 log.info('creating repo %s in %s', repo_name, repo_path)
98 log.info('creating repo %s in %s', repo_name, repo_path)
100 from vcs.backends.hg import MercurialRepository
99 from vcs.backends.hg import MercurialRepository
101 MercurialRepository(repo_path, create=True)
100 MercurialRepository(repo_path, create=True)
102
101
@@ -1,76 +1,81
1 import logging
1 import logging
2 import os
2 import os
3 from pylons import request, response, session, tmpl_context as c, url, app_globals as g
3 from pylons import request, response, session, tmpl_context as c, url, app_globals as g
4 from pylons.controllers.util import abort, redirect
4 from pylons.controllers.util import abort, redirect
5 from pylons_app.lib import auth
5 from pylons_app.lib import auth
6 from pylons_app.lib.base import BaseController, render
6 from pylons_app.lib.base import BaseController, render
7 from pylons_app.model import meta
7 from pylons_app.model import meta
8 from pylons_app.model.db import Users, UserLogs
8 from pylons_app.model.db import Users, UserLogs
9 from pylons_app.lib.auth import authenticate
9 from pylons_app.lib.auth import authenticate
10 from pylons_app.model.hg_model import HgModel
10 from pylons_app.model.hg_model import HgModel
11 from operator import itemgetter
11 from operator import itemgetter
12 import shutil
12 import shutil
13 from pylons_app.lib.utils import invalidate_cache
13 log = logging.getLogger(__name__)
14 log = logging.getLogger(__name__)
14
15
15 class ReposController(BaseController):
16 class ReposController(BaseController):
16 """REST Controller styled on the Atom Publishing Protocol"""
17 """REST Controller styled on the Atom Publishing Protocol"""
17 # To properly map this controller, ensure your config/routing.py
18 # To properly map this controller, ensure your config/routing.py
18 # file has a resource setup:
19 # file has a resource setup:
19 # map.resource('repo', 'repos')
20 # map.resource('repo', 'repos')
20
21
21 @authenticate
22 @authenticate
22 def __before__(self):
23 def __before__(self):
23
24
24 c.admin_user = session.get('admin_user')
25 c.admin_user = session.get('admin_user')
25 c.admin_username = session.get('admin_username')
26 c.admin_username = session.get('admin_username')
26 self.sa = meta.Session
27 self.sa = meta.Session
27
28
28 def index(self, format='html'):
29 def index(self, format='html'):
29 """GET /repos: All items in the collection"""
30 """GET /repos: All items in the collection"""
30 # url('repos')
31 # url('repos')
31 hg_model = HgModel()
32 hg_model = HgModel()
32 c.repos_list = list(hg_model.get_repos())
33 c.repos_list = list(hg_model.get_repos())
33 c.repos_list.sort(key=itemgetter('name'))
34 c.repos_list.sort(key=itemgetter('name'))
34 return render('admin/repos/repos.html')
35 return render('admin/repos/repos.html')
35
36
36 def create(self):
37 def create(self):
37 """POST /repos: Create a new item"""
38 """POST /repos: Create a new item"""
38 # url('repos')
39 # url('repos')
39
40
40 def new(self, format='html'):
41 def new(self, format='html'):
41 """GET /repos/new: Form to create a new item"""
42 """GET /repos/new: Form to create a new item"""
42 # url('new_repo')
43 # url('new_repo')
43
44
44 def update(self, id):
45 def update(self, id):
45 """PUT /repos/id: Update an existing item"""
46 """PUT /repos/id: Update an existing item"""
46 # Forms posted to this method should contain a hidden field:
47 # Forms posted to this method should contain a hidden field:
47 # <input type="hidden" name="_method" value="PUT" />
48 # <input type="hidden" name="_method" value="PUT" />
48 # Or using helpers:
49 # Or using helpers:
49 # h.form(url('repo', id=ID),
50 # h.form(url('repo', id=ID),
50 # method='put')
51 # method='put')
51 # url('repo', id=ID)
52 # url('repo', id=ID)
52
53
53 def delete(self, id):
54 def delete(self, id):
54 """DELETE /repos/id: Delete an existing item"""
55 """DELETE /repos/id: Delete an existing item"""
55 # Forms posted to this method should contain a hidden field:
56 # Forms posted to this method should contain a hidden field:
56 # <input type="hidden" name="_method" value="DELETE" />
57 # <input type="hidden" name="_method" value="DELETE" />
57 # Or using helpers:
58 # Or using helpers:
58 # h.form(url('repo', id=ID),
59 # h.form(url('repo', id=ID),
59 # method='delete')
60 # method='delete')
60 # url('repo', id=ID)
61 # url('repo', id=ID)
61 from datetime import datetime
62 from datetime import datetime
62 path = g.paths[0][1].replace('*', '')
63 path = g.paths[0][1].replace('*', '')
63 rm_path = os.path.join(path, id)
64 rm_path = os.path.join(path, id)
64 log.info("Removing %s", rm_path)
65 log.info("Removing %s", rm_path)
65 shutil.move(os.path.join(rm_path, '.hg'), os.path.join(rm_path, 'rm__.hg'))
66 shutil.move(os.path.join(rm_path, '.hg'), os.path.join(rm_path, 'rm__.hg'))
66 shutil.move(rm_path, os.path.join(path, 'rm__%s-%s' % (datetime.today(), id)))
67 shutil.move(rm_path, os.path.join(path, 'rm__%s-%s' % (datetime.today(), id)))
68
69 #clear our cached list for refresh with new repo
70 invalidate_cache('repo_list_2')
71
67 return redirect(url('repos'))
72 return redirect(url('repos'))
68
73
69
74
70 def show(self, id, format='html'):
75 def show(self, id, format='html'):
71 """GET /repos/id: Show a specific item"""
76 """GET /repos/id: Show a specific item"""
72 # url('repo', id=ID)
77 # url('repo', id=ID)
73 return render('/repos_show.html')
78 return render('/repos_show.html')
74 def edit(self, id, format='html'):
79 def edit(self, id, format='html'):
75 """GET /repos/id/edit: Form to edit an existing item"""
80 """GET /repos/id/edit: Form to edit an existing item"""
76 # url('edit_repo', id=ID)
81 # url('edit_repo', id=ID)
@@ -1,106 +1,114
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):
94 from beaker.cache import region_invalidate
95 if name == 'repo_list_2':
96 log.info('INVALIDATING CACHE FOR %s', name)
97 from pylons_app.lib.base import _get_repos
98 #clear our cached list for refresh with new repo
99 region_invalidate(_get_repos, None, 'repo_list_2')
100
93 from vcs.backends.base import BaseChangeset
101 from vcs.backends.base import BaseChangeset
94 from vcs.utils.lazy import LazyProperty
102 from vcs.utils.lazy import LazyProperty
95 class EmptyChangeset(BaseChangeset):
103 class EmptyChangeset(BaseChangeset):
96
104
97 revision = -1
105 revision = -1
98
106
99 @LazyProperty
107 @LazyProperty
100 def raw_id(self):
108 def raw_id(self):
101 """
109 """
102 Returns raw string identifing this changeset, useful for web
110 Returns raw string identifing this changeset, useful for web
103 representation.
111 representation.
104 """
112 """
105 return '0' * 12
113 return '0' * 12
106
114
General Comments 0
You need to be logged in to leave comments. Login now