##// END OF EJS Templates
Reimplemented way of caching repos list, hg model now get's repos objects right from cached dict, this way we skipp creating instances of MercurialRepository and gain performance. Some import cleanup
marcink -
r245:a83a1799 default
parent child Browse files
Show More
@@ -1,15 +1,11 b''
1 from pylons import tmpl_context as c, app_globals as g
2 from pylons_app.lib.auth import LoginRequired
3 from pylons_app.lib.base import BaseController, render
4 from pylons_app.model.hg_model import HgModel
1 import logging
5 import logging
2
6
3 from pylons import tmpl_context as c, app_globals as g, session, request, config, url
4 from pylons.controllers.util import abort, redirect
5
6 from pylons_app.lib.base import BaseController, render
7 from pylons_app.lib.utils import get_repo_slug
8 from pylons_app.model.hg_model import HgModel
9 from pylons_app.lib.auth import LoginRequired
10 log = logging.getLogger(__name__)
7 log = logging.getLogger(__name__)
11
8
12
13 class BranchesController(BaseController):
9 class BranchesController(BaseController):
14
10
15 @LoginRequired()
11 @LoginRequired()
@@ -1,11 +1,10 b''
1 from mercurial.graphmod import revisions as graph_rev, colored, CHANGESET
1 from mercurial.graphmod import revisions as graph_rev, colored, CHANGESET
2 from mercurial.node import short
2 from mercurial.node import short
3 from pylons import request, response, session, tmpl_context as c, url, config, \
3 from pylons import request, session, tmpl_context as c
4 app_globals as g
5 from pylons.controllers.util import abort, redirect
6 from pylons_app.lib.auth import LoginRequired
4 from pylons_app.lib.auth import LoginRequired
7 from pylons_app.lib.base import BaseController, render, _full_changelog_cached
5 from pylons_app.lib.base import BaseController, render
8 from pylons_app.lib.filters import age as _age, person
6 from pylons_app.lib.filters import age as _age, person
7 from pylons_app.model.hg_model import _full_changelog_cached
9 from simplejson import dumps
8 from simplejson import dumps
10 from webhelpers.paginate import Page
9 from webhelpers.paginate import Page
11 import logging
10 import logging
@@ -1,6 +1,4 b''
1 from pylons import request, response, session, tmpl_context as c, url, config, \
1 from pylons import tmpl_context as c
2 app_globals as g
3 from pylons.controllers.util import abort, redirect
4 from pylons_app.lib.auth import LoginRequired
2 from pylons_app.lib.auth import LoginRequired
5 from pylons_app.lib.base import BaseController, render
3 from pylons_app.lib.base import BaseController, render
6 from pylons_app.model.hg_model import HgModel
4 from pylons_app.model.hg_model import HgModel
@@ -1,13 +1,10 b''
1 #!/usr/bin/python
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
2 # -*- coding: utf-8 -*-
3 from pylons import tmpl_context as c, url, response
4 from pylons_app.lib.base import BaseController, render
5 from pylons_app.model.hg_model import _full_changelog_cached
6 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
3 import logging
7 import logging
4 from operator import itemgetter
5 from pylons import tmpl_context as c, request, config, url, response
6 from pylons_app.lib.base import BaseController, render, _full_changelog_cached
7 from pylons_app.lib.utils import get_repo_slug
8 from pylons_app.model.hg_model import HgModel
9 from pylons_app.lib.auth import LoginRequired
10 from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
11 log = logging.getLogger(__name__)
8 log = logging.getLogger(__name__)
12
9
13 class FeedController(BaseController):
10 class FeedController(BaseController):
@@ -35,7 +32,8 b' class FeedController(BaseController):'
35 if cnt > self.feed_nr:
32 if cnt > self.feed_nr:
36 break
33 break
37 feed.add_item(title=cs.message,
34 feed.add_item(title=cs.message,
38 link=url('changeset_home', repo_name=repo_name, revision=cs.raw_id, qualified=True),
35 link=url('changeset_home', repo_name=repo_name,
36 revision=cs.raw_id, qualified=True),
39 description=str(cs.date))
37 description=str(cs.date))
40
38
41 response.content_type = feed.mime_type
39 response.content_type = feed.mime_type
@@ -1,15 +1,12 b''
1 import tempfile
1 from mercurial import archival
2 from pylons import request, response, session, tmpl_context as c, url, config, \
2 from pylons import request, response, session, tmpl_context as c, url
3 app_globals as g
4 from pylons.controllers.util import abort, redirect
5 from pylons_app.lib.auth import LoginRequired
3 from pylons_app.lib.auth import LoginRequired
6 from pylons_app.lib.base import BaseController, render
4 from pylons_app.lib.base import BaseController, render
7 from pylons_app.lib.utils import get_repo_slug
8 from pylons_app.model.hg_model import HgModel
5 from pylons_app.model.hg_model import HgModel
9 from vcs.exceptions import RepositoryError, ChangesetError
6 from vcs.exceptions import RepositoryError, ChangesetError
10 from vcs.utils import diffs as differ
7 from vcs.utils import diffs as differ
11 import logging
8 import logging
12 from mercurial import archival
9 import tempfile
13
10
14
11
15 log = logging.getLogger(__name__)
12 log = logging.getLogger(__name__)
@@ -1,10 +1,11 b''
1 #!/usr/bin/python
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
2 # -*- coding: utf-8 -*-
3 import logging
4 from operator import itemgetter
3 from operator import itemgetter
5 from pylons import tmpl_context as c, request, config
4 from pylons import tmpl_context as c, request, config
5 from pylons_app.lib.auth import LoginRequired
6 from pylons_app.lib.base import BaseController, render
6 from pylons_app.lib.base import BaseController, render
7 from pylons_app.lib.auth import LoginRequired
7 from pylons_app.model.hg_model import HgModel
8 import logging
8 log = logging.getLogger(__name__)
9 log = logging.getLogger(__name__)
9
10
10 class HgController(BaseController):
11 class HgController(BaseController):
@@ -18,12 +19,12 b' class HgController(BaseController):'
18 cs = c.current_sort
19 cs = c.current_sort
19 c.cs_slug = cs.replace('-', '')
20 c.cs_slug = cs.replace('-', '')
20 sortables = ['name', 'description', 'last_change', 'tip', 'contact']
21 sortables = ['name', 'description', 'last_change', 'tip', 'contact']
21
22 cached_repo_list = HgModel().get_repos()
22 if cs and c.cs_slug in sortables:
23 if cs and c.cs_slug in sortables:
23 sort_key = c.cs_slug + '_sort'
24 sort_key = c.cs_slug + '_sort'
24 if cs.startswith('-'):
25 if cs.startswith('-'):
25 c.repos_list = sorted(c.cached_repo_list, key=itemgetter(sort_key), reverse=True)
26 c.repos_list = sorted(cached_repo_list, key=itemgetter(sort_key), reverse=True)
26 else:
27 else:
27 c.repos_list = sorted(c.cached_repo_list, key=itemgetter(sort_key), reverse=False)
28 c.repos_list = sorted(cached_repo_list, key=itemgetter(sort_key), reverse=False)
28
29
29 return render('/index.html')
30 return render('/index.html')
@@ -1,13 +1,9 b''
1 import logging
1 from pylons import tmpl_context as c, request
2
2 from pylons_app.lib.auth import LoginRequired
3 from pylons import tmpl_context as c, app_globals as g, session, request, config, url
4 from pylons.controllers.util import abort, redirect
5
6 from pylons_app.lib.base import BaseController, render
3 from pylons_app.lib.base import BaseController, render
7 from pylons_app.lib.utils import get_repo_slug
8 from pylons_app.model.hg_model import HgModel
4 from pylons_app.model.hg_model import HgModel
9 from webhelpers.paginate import Page
5 from webhelpers.paginate import Page
10 from pylons_app.lib.auth import LoginRequired
6 import logging
11
7
12 log = logging.getLogger(__name__)
8 log = logging.getLogger(__name__)
13
9
@@ -1,7 +1,7 b''
1 from pylons import tmpl_context as c, request
1 from pylons import tmpl_context as c, request
2 from pylons_app.lib.auth import LoginRequired
2 from pylons_app.lib.auth import LoginRequired
3 from pylons_app.lib.base import BaseController, render, _full_changelog_cached
3 from pylons_app.lib.base import BaseController, render
4 from pylons_app.model.hg_model import HgModel
4 from pylons_app.model.hg_model import HgModel, _full_changelog_cached
5 import logging
5 import logging
6
6
7 log = logging.getLogger(__name__)
7 log = logging.getLogger(__name__)
@@ -16,7 +16,6 b' class SummaryController(BaseController):'
16 hg_model = HgModel()
16 hg_model = HgModel()
17 c.repo_info = hg_model.get_repo(c.repo_name)
17 c.repo_info = hg_model.get_repo(c.repo_name)
18 c.repo_changesets = _full_changelog_cached(c.repo_name)[:10]
18 c.repo_changesets = _full_changelog_cached(c.repo_name)[:10]
19
20 e = request.environ
19 e = request.environ
21 uri = u'%(protocol)s://%(user)s@%(host)s/%(repo_name)s' % {
20 uri = u'%(protocol)s://%(user)s@%(host)s/%(repo_name)s' % {
22 'protocol': e.get('wsgi.url_scheme'),
21 'protocol': e.get('wsgi.url_scheme'),
@@ -1,15 +1,11 b''
1 from pylons import tmpl_context as c
2 from pylons_app.lib.auth import LoginRequired
3 from pylons_app.lib.base import BaseController, render
4 from pylons_app.model.hg_model import HgModel
1 import logging
5 import logging
2
6
3 from pylons import tmpl_context as c, app_globals as g, session, request, config, url
4 from pylons.controllers.util import abort, redirect
5
6 from pylons_app.lib.base import BaseController, render
7 from pylons_app.lib.utils import get_repo_slug
8 from pylons_app.model.hg_model import HgModel
9 from pylons_app.lib.auth import LoginRequired
10 log = logging.getLogger(__name__)
7 log = logging.getLogger(__name__)
11
8
12
13 class TagsController(BaseController):
9 class TagsController(BaseController):
14
10
15 @LoginRequired()
11 @LoginRequired()
@@ -1,9 +1,8 b''
1 from formencode import htmlfill
1 from formencode import htmlfill
2 from pylons import request, response, session, tmpl_context as c, url, \
2 from pylons import request, session, tmpl_context as c, url
3 app_globals as g
3 from pylons.controllers.util import abort, redirect
4 from pylons.i18n.translation import _
4 from pylons.i18n.translation import _
5 from pylons_app.lib import helpers as h
5 from pylons_app.lib import helpers as h
6 from pylons.controllers.util import abort, redirect
7 from pylons_app.lib.auth import LoginRequired, CheckPermissionAll
6 from pylons_app.lib.auth import LoginRequired, CheckPermissionAll
8 from pylons_app.lib.base import BaseController, render
7 from pylons_app.lib.base import BaseController, render
9 from pylons_app.model.db import User, UserLog
8 from pylons_app.model.db import User, UserLog
@@ -12,8 +11,6 b' from pylons_app.model.user_model import '
12 import formencode
11 import formencode
13 import logging
12 import logging
14
13
15
16
17 log = logging.getLogger(__name__)
14 log = logging.getLogger(__name__)
18
15
19 class UsersController(BaseController):
16 class UsersController(BaseController):
@@ -2,24 +2,15 b''
2
2
3 Provides the BaseController class for subclassing.
3 Provides the BaseController class for subclassing.
4 """
4 """
5 from beaker.cache import cache_region
6 from pylons import config, tmpl_context as c, request, session
5 from pylons import config, tmpl_context as c, request, session
7 from pylons.controllers import WSGIController
6 from pylons.controllers import WSGIController
8 from pylons.templating import render_mako as render
7 from pylons.templating import render_mako as render
9 from pylons_app.lib.auth import LoginRequired, AuthUser
8 from pylons_app.lib.auth import LoginRequired, AuthUser
10 from pylons_app.lib.utils import get_repo_slug
9 from pylons_app.lib.utils import get_repo_slug
11 from pylons_app.model import meta
10 from pylons_app.model import meta
12 from pylons_app.model.hg_model import HgModel
11 from pylons_app.model.hg_model import _get_repos_cached
13 from pylons_app import __version__
12 from pylons_app import __version__
14
13
15 @cache_region('long_term', 'cached_repo_list')
16 def _get_repos_cached():
17 return [rep for rep in HgModel().get_repos()]
18
19 @cache_region('long_term', 'full_changelog')
20 def _full_changelog_cached(repo_name):
21 return list(reversed(list(HgModel().get_repo(repo_name))))
22
23 class BaseController(WSGIController):
14 class BaseController(WSGIController):
24
15
25 def __before__(self):
16 def __before__(self):
@@ -107,11 +107,11 b' def invalidate_cache(name, *args):'
107 args = tuple(tmp)
107 args = tuple(tmp)
108
108
109 if name == 'cached_repo_list':
109 if name == 'cached_repo_list':
110 from pylons_app.lib.base import _get_repos_cached
110 from pylons_app.model.hg_model import _get_repos_cached
111 region_invalidate(_get_repos_cached, None, *args)
111 region_invalidate(_get_repos_cached, None, *args)
112
112
113 if name == 'full_changelog':
113 if name == 'full_changelog':
114 from pylons_app.lib.base import _full_changelog_cached
114 from pylons_app.model.hg_model import _full_changelog_cached
115 region_invalidate(_full_changelog_cached, None, *args)
115 region_invalidate(_full_changelog_cached, None, *args)
116
116
117 from vcs.backends.base import BaseChangeset
117 from vcs.backends.base import BaseChangeset
@@ -128,3 +128,17 b' class EmptyChangeset(BaseChangeset):'
128 """
128 """
129 return '0' * 12
129 return '0' * 12
130
130
131
132 def repo2db_mapper():
133 """
134 put !
135 """
136 pass
137 #scann all dirs for .hgdbid
138 #if some dir doesn't have one generate one.
139 #
140
141
142
143
144
@@ -3,65 +3,118 b''
3 #
3 #
4 # Copyright (c) 2010 marcink. All rights reserved.
4 # Copyright (c) 2010 marcink. All rights reserved.
5 #
5 #
6 from vcs.exceptions import RepositoryError
7 '''
6 '''
8 Created on Apr 9, 2010
7 Created on Apr 9, 2010
9
8
10 @author: marcink
9 @author: marcink
11 '''
10 '''
11
12 from beaker.cache import cache_region
13 from mercurial import ui
14 from mercurial.hgweb.hgwebdir_mod import findrepos
15 from pylons import app_globals as g
16 from vcs.exceptions import RepositoryError, VCSError
17 import logging
12 import os
18 import os
13 from pylons import tmpl_context as c, app_globals as g, session, request, config
14 from pylons.controllers.util import abort
15 import sys
19 import sys
20 log = logging.getLogger(__name__)
21
16 try:
22 try:
17 from vcs.backends.hg import get_repositories, MercurialRepository
23 from vcs.backends.hg import MercurialRepository
18 except ImportError:
24 except ImportError:
19 sys.stderr.write('You have to import vcs module')
25 sys.stderr.write('You have to import vcs module')
20 raise Exception('Unable to import vcs')
26 raise Exception('Unable to import vcs')
21
27
28
29 @cache_region('long_term', 'cached_repo_list')
30 def _get_repos_cached():
31 """
32 return cached dict with repos
33 """
34 return HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui)
35
36 @cache_region('long_term', 'full_changelog')
37 def _full_changelog_cached(repo_name):
38 log.info('getting full changelog for %s', repo_name)
39 return list(reversed(list(HgModel().get_repo(repo_name))))
40
22 class HgModel(object):
41 class HgModel(object):
23 """
42 """
24 Mercurial Model
43 Mercurial Model
25 """
44 """
26
45
27
28 def __init__(self):
46 def __init__(self):
29 """
47 """
30 Constructor
48 Constructor
31 """
49 """
32 pass
50 pass
33
51
52 @staticmethod
53 def repo_scan(repos_prefix, repos_path, baseui):
54 """
55 Listing of repositories in given path. This path should not be a
56 repository itself. Return a dictionary of repository objects
57 :param repos_path: path to directory it could take syntax with
58 * or ** for deep recursive displaying repositories
59 """
60 def check_repo_dir(path):
61 """
62 Checks the repository
63 :param path:
64 """
65 repos_path = path.split('/')
66 if repos_path[-1] in ['*', '**']:
67 repos_path = repos_path[:-1]
68 if repos_path[0] != '/':
69 repos_path[0] = '/'
70 if not os.path.isdir(os.path.join(*repos_path)):
71 raise RepositoryError('Not a valid repository in %s' % path[0][1])
72 if not repos_path.endswith('*'):
73 raise VCSError('You need to specify * or ** at the end of path '
74 'for recursive scanning')
75
76 check_repo_dir(repos_path)
77 log.info('scanning for repositories in %s', repos_path)
78 repos = findrepos([(repos_prefix, repos_path)])
79 if not isinstance(baseui, ui.ui):
80 baseui = ui.ui()
81
82 repos_list = {}
83 for name, path in repos:
84 try:
85 repos_list[name] = MercurialRepository(path, baseui=baseui)
86 except OSError:
87 continue
88 return repos_list
89
34 def get_repos(self):
90 def get_repos(self):
35 for mercurial_repo in get_repositories(g.paths[0][0], g.paths[0][1], g.baseui):
91 for name, repo in _get_repos_cached().items():
36
92 if repo._get_hidden():
37 if mercurial_repo._get_hidden():
38 #skip hidden web repository
93 #skip hidden web repository
39 continue
94 continue
40
95
41 last_change = mercurial_repo.last_change
96 last_change = repo.last_change
42 try:
97 try:
43 tip = mercurial_repo.get_changeset('tip')
98 tip = repo.get_changeset('tip')
44 except RepositoryError:
99 except RepositoryError:
45 from pylons_app.lib.utils import EmptyChangeset
100 from pylons_app.lib.utils import EmptyChangeset
46 tip = EmptyChangeset()
101 tip = EmptyChangeset()
47
102
48 tmp_d = {}
103 tmp_d = {}
49 tmp_d['name'] = mercurial_repo.name
104 tmp_d['name'] = repo.name
50 tmp_d['name_sort'] = tmp_d['name'].lower()
105 tmp_d['name_sort'] = tmp_d['name'].lower()
51 tmp_d['description'] = mercurial_repo.description
106 tmp_d['description'] = repo.description
52 tmp_d['description_sort'] = tmp_d['description']
107 tmp_d['description_sort'] = tmp_d['description']
53 tmp_d['last_change'] = last_change
108 tmp_d['last_change'] = last_change
54 tmp_d['last_change_sort'] = last_change[1] - last_change[0]
109 tmp_d['last_change_sort'] = last_change[1] - last_change[0]
55 tmp_d['tip'] = tip.raw_id
110 tmp_d['tip'] = tip.raw_id
56 tmp_d['tip_sort'] = tip.revision
111 tmp_d['tip_sort'] = tip.revision
57 tmp_d['rev'] = tip.revision
112 tmp_d['rev'] = tip.revision
58 tmp_d['contact'] = mercurial_repo.contact
113 tmp_d['contact'] = repo.contact
59 tmp_d['contact_sort'] = tmp_d['contact']
114 tmp_d['contact_sort'] = tmp_d['contact']
60 tmp_d['repo_archives'] = list(mercurial_repo._get_archives())
115 tmp_d['repo_archives'] = list(repo._get_archives())
61
116
62 yield tmp_d
117 yield tmp_d
63
118
64 def get_repo(self, repo_name):
119 def get_repo(self, repo_name):
65 path = g.paths[0][1].replace('*', '')
120 return _get_repos_cached()[repo_name]
66 repo = MercurialRepository(os.path.join(path, repo_name), baseui=g.baseui)
67 return repo
@@ -92,8 +92,8 b' def is_current(selected):'
92 <a id="repo_switcher" title="${_('Switch repository')}" href="#">&darr;</a>
92 <a id="repo_switcher" title="${_('Switch repository')}" href="#">&darr;</a>
93 <div id="switch_repos" style="display:none;position: absolute;width: 150px;height: 25px">
93 <div id="switch_repos" style="display:none;position: absolute;width: 150px;height: 25px">
94 <select id="repos_list" size="=10">
94 <select id="repos_list" size="=10">
95 %for repo in c.cached_repo_list:
95 %for repo in c.cached_repo_list.values():
96 <option value="${repo['name']}">${repo['name']}</option>
96 <option value="${repo.name}">${repo.name}</option>
97 %endfor
97 %endfor
98 </select>
98 </select>
99 </div>
99 </div>
General Comments 0
You need to be logged in to leave comments. Login now