##// END OF EJS Templates
added limit for showing pygemntized source codes larger than 250kb.
marcink -
r485:9836541b celery
parent child Browse files
Show More
@@ -1,168 +1,171 b''
1 """Routes configuration
1 """Routes configuration
2
2
3 The more specific and detailed routes should be defined first so they
3 The more specific and detailed routes should be defined first so they
4 may take precedent over the more generic routes. For more information
4 may take precedent over the more generic routes. For more information
5 refer to the routes manual at http://routes.groovie.org/docs/
5 refer to the routes manual at http://routes.groovie.org/docs/
6 """
6 """
7 from __future__ import with_statement
7 from __future__ import with_statement
8 from routes import Mapper
8 from routes import Mapper
9 from pylons_app.lib.utils import check_repo_fast as cr
9 from pylons_app.lib.utils import check_repo_fast as cr
10
10
11 def make_map(config):
11 def make_map(config):
12 """Create, configure and return the routes Mapper"""
12 """Create, configure and return the routes Mapper"""
13 map = Mapper(directory=config['pylons.paths']['controllers'],
13 map = Mapper(directory=config['pylons.paths']['controllers'],
14 always_scan=config['debug'])
14 always_scan=config['debug'])
15 map.minimization = False
15 map.minimization = False
16 map.explicit = False
16 map.explicit = False
17
17
18 # The ErrorController route (handles 404/500 error pages); it should
18 # The ErrorController route (handles 404/500 error pages); it should
19 # likely stay at the top, ensuring it can always be resolved
19 # likely stay at the top, ensuring it can always be resolved
20 map.connect('/error/{action}', controller='error')
20 map.connect('/error/{action}', controller='error')
21 map.connect('/error/{action}/{id}', controller='error')
21 map.connect('/error/{action}/{id}', controller='error')
22
22
23 # CUSTOM ROUTES HERE
23 # CUSTOM ROUTES HERE
24 map.connect('hg_home', '/', controller='hg', action='index')
24 map.connect('hg_home', '/', controller='hg', action='index')
25
25
26 def check_repo(environ, match_dict):
26 def check_repo(environ, match_dict):
27 """
27 """
28 check for valid repository for proper 404 handling
28 check for valid repository for proper 404 handling
29 @param environ:
29 @param environ:
30 @param match_dict:
30 @param match_dict:
31 """
31 """
32 repo_name = match_dict.get('repo_name')
32 repo_name = match_dict.get('repo_name')
33 return not cr(repo_name, config['base_path'])
33 return not cr(repo_name, config['base_path'])
34
34
35 #REST REPO MAP
35 #REST REPO MAP
36 with map.submapper(path_prefix='/_admin', controller='admin/repos') as m:
36 with map.submapper(path_prefix='/_admin', controller='admin/repos') as m:
37 m.connect("repos", "/repos",
37 m.connect("repos", "/repos",
38 action="create", conditions=dict(method=["POST"]))
38 action="create", conditions=dict(method=["POST"]))
39 m.connect("repos", "/repos",
39 m.connect("repos", "/repos",
40 action="index", conditions=dict(method=["GET"]))
40 action="index", conditions=dict(method=["GET"]))
41 m.connect("formatted_repos", "/repos.{format}",
41 m.connect("formatted_repos", "/repos.{format}",
42 action="index",
42 action="index",
43 conditions=dict(method=["GET"]))
43 conditions=dict(method=["GET"]))
44 m.connect("new_repo", "/repos/new",
44 m.connect("new_repo", "/repos/new",
45 action="new", conditions=dict(method=["GET"]))
45 action="new", conditions=dict(method=["GET"]))
46 m.connect("formatted_new_repo", "/repos/new.{format}",
46 m.connect("formatted_new_repo", "/repos/new.{format}",
47 action="new", conditions=dict(method=["GET"]))
47 action="new", conditions=dict(method=["GET"]))
48 m.connect("/repos/{repo_name:.*}",
48 m.connect("/repos/{repo_name:.*}",
49 action="update", conditions=dict(method=["PUT"],
49 action="update", conditions=dict(method=["PUT"],
50 function=check_repo))
50 function=check_repo))
51 m.connect("/repos/{repo_name:.*}",
51 m.connect("/repos/{repo_name:.*}",
52 action="delete", conditions=dict(method=["DELETE"],
52 action="delete", conditions=dict(method=["DELETE"],
53 function=check_repo))
53 function=check_repo))
54 m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
54 m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
55 action="edit", conditions=dict(method=["GET"],
55 action="edit", conditions=dict(method=["GET"],
56 function=check_repo))
56 function=check_repo))
57 m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
57 m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
58 action="edit", conditions=dict(method=["GET"],
58 action="edit", conditions=dict(method=["GET"],
59 function=check_repo))
59 function=check_repo))
60 m.connect("repo", "/repos/{repo_name:.*}",
60 m.connect("repo", "/repos/{repo_name:.*}",
61 action="show", conditions=dict(method=["GET"],
61 action="show", conditions=dict(method=["GET"],
62 function=check_repo))
62 function=check_repo))
63 m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
63 m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
64 action="show", conditions=dict(method=["GET"],
64 action="show", conditions=dict(method=["GET"],
65 function=check_repo))
65 function=check_repo))
66 #ajax delete repo perm user
66 #ajax delete repo perm user
67 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
67 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
68 action="delete_perm_user", conditions=dict(method=["DELETE"],
68 action="delete_perm_user", conditions=dict(method=["DELETE"],
69 function=check_repo))
69 function=check_repo))
70
70
71 map.resource('user', 'users', controller='admin/users', path_prefix='/_admin')
71 map.resource('user', 'users', controller='admin/users', path_prefix='/_admin')
72 map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin')
72 map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin')
73
73
74 #REST SETTINGS MAP
74 #REST SETTINGS MAP
75 with map.submapper(path_prefix='/_admin', controller='admin/settings') as m:
75 with map.submapper(path_prefix='/_admin', controller='admin/settings') as m:
76 m.connect("admin_settings", "/settings",
76 m.connect("admin_settings", "/settings",
77 action="create", conditions=dict(method=["POST"]))
77 action="create", conditions=dict(method=["POST"]))
78 m.connect("admin_settings", "/settings",
78 m.connect("admin_settings", "/settings",
79 action="index", conditions=dict(method=["GET"]))
79 action="index", conditions=dict(method=["GET"]))
80 m.connect("formatted_admin_settings", "/settings.{format}",
80 m.connect("formatted_admin_settings", "/settings.{format}",
81 action="index", conditions=dict(method=["GET"]))
81 action="index", conditions=dict(method=["GET"]))
82 m.connect("admin_new_setting", "/settings/new",
82 m.connect("admin_new_setting", "/settings/new",
83 action="new", conditions=dict(method=["GET"]))
83 action="new", conditions=dict(method=["GET"]))
84 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
84 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
85 action="new", conditions=dict(method=["GET"]))
85 action="new", conditions=dict(method=["GET"]))
86 m.connect("/settings/{setting_id}",
86 m.connect("/settings/{setting_id}",
87 action="update", conditions=dict(method=["PUT"]))
87 action="update", conditions=dict(method=["PUT"]))
88 m.connect("/settings/{setting_id}",
88 m.connect("/settings/{setting_id}",
89 action="delete", conditions=dict(method=["DELETE"]))
89 action="delete", conditions=dict(method=["DELETE"]))
90 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
90 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
91 action="edit", conditions=dict(method=["GET"]))
91 action="edit", conditions=dict(method=["GET"]))
92 m.connect("formatted_admin_edit_setting", "/settings/{setting_id}.{format}/edit",
92 m.connect("formatted_admin_edit_setting", "/settings/{setting_id}.{format}/edit",
93 action="edit", conditions=dict(method=["GET"]))
93 action="edit", conditions=dict(method=["GET"]))
94 m.connect("admin_setting", "/settings/{setting_id}",
94 m.connect("admin_setting", "/settings/{setting_id}",
95 action="show", conditions=dict(method=["GET"]))
95 action="show", conditions=dict(method=["GET"]))
96 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
96 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
97 action="show", conditions=dict(method=["GET"]))
97 action="show", conditions=dict(method=["GET"]))
98 m.connect("admin_settings_my_account", "/my_account",
98 m.connect("admin_settings_my_account", "/my_account",
99 action="my_account", conditions=dict(method=["GET"]))
99 action="my_account", conditions=dict(method=["GET"]))
100 m.connect("admin_settings_my_account_update", "/my_account_update",
100 m.connect("admin_settings_my_account_update", "/my_account_update",
101 action="my_account_update", conditions=dict(method=["PUT"]))
101 action="my_account_update", conditions=dict(method=["PUT"]))
102 m.connect("admin_settings_create_repository", "/create_repository",
102 m.connect("admin_settings_create_repository", "/create_repository",
103 action="create_repository", conditions=dict(method=["GET"]))
103 action="create_repository", conditions=dict(method=["GET"]))
104
104
105 #ADMIN
105 #ADMIN
106 with map.submapper(path_prefix='/_admin', controller='admin/admin') as m:
106 with map.submapper(path_prefix='/_admin', controller='admin/admin') as m:
107 m.connect('admin_home', '', action='index')#main page
107 m.connect('admin_home', '', action='index')#main page
108 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
108 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
109 action='add_repo')
109 action='add_repo')
110 #SEARCH
110 #SEARCH
111 map.connect('search', '/_admin/search', controller='search')
111 map.connect('search', '/_admin/search', controller='search')
112
112
113 #LOGIN/LOGOUT/REGISTER/SIGN IN
113 #LOGIN/LOGOUT/REGISTER/SIGN IN
114 map.connect('login_home', '/_admin/login', controller='login')
114 map.connect('login_home', '/_admin/login', controller='login')
115 map.connect('logout_home', '/_admin/logout', controller='login', action='logout')
115 map.connect('logout_home', '/_admin/logout', controller='login', action='logout')
116 map.connect('register', '/_admin/register', controller='login', action='register')
116 map.connect('register', '/_admin/register', controller='login', action='register')
117 map.connect('reset_password', '/_admin/password_reset', controller='login', action='password_reset')
117 map.connect('reset_password', '/_admin/password_reset', controller='login', action='password_reset')
118
118
119 #FEEDS
119 #FEEDS
120 map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
120 map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
121 controller='feed', action='rss',
121 controller='feed', action='rss',
122 conditions=dict(function=check_repo))
122 conditions=dict(function=check_repo))
123 map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
123 map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
124 controller='feed', action='atom',
124 controller='feed', action='atom',
125 conditions=dict(function=check_repo))
125 conditions=dict(function=check_repo))
126
126
127
127
128 #OTHERS
128 #OTHERS
129 map.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
129 map.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
130 controller='changeset', revision='tip',
130 controller='changeset', revision='tip',
131 conditions=dict(function=check_repo))
131 conditions=dict(function=check_repo))
132 map.connect('raw_changeset_home', '/{repo_name:.*}/raw-changeset/{revision}',
132 map.connect('raw_changeset_home', '/{repo_name:.*}/raw-changeset/{revision}',
133 controller='changeset',action='raw_changeset', revision='tip',
133 controller='changeset', action='raw_changeset', revision='tip',
134 conditions=dict(function=check_repo))
134 conditions=dict(function=check_repo))
135 map.connect('summary_home', '/{repo_name:.*}/summary',
135 map.connect('summary_home', '/{repo_name:.*}/summary',
136 controller='summary', conditions=dict(function=check_repo))
136 controller='summary', conditions=dict(function=check_repo))
137 map.connect('shortlog_home', '/{repo_name:.*}/shortlog',
137 map.connect('shortlog_home', '/{repo_name:.*}/shortlog',
138 controller='shortlog', conditions=dict(function=check_repo))
138 controller='shortlog', conditions=dict(function=check_repo))
139 map.connect('branches_home', '/{repo_name:.*}/branches',
139 map.connect('branches_home', '/{repo_name:.*}/branches',
140 controller='branches', conditions=dict(function=check_repo))
140 controller='branches', conditions=dict(function=check_repo))
141 map.connect('tags_home', '/{repo_name:.*}/tags',
141 map.connect('tags_home', '/{repo_name:.*}/tags',
142 controller='tags', conditions=dict(function=check_repo))
142 controller='tags', conditions=dict(function=check_repo))
143 map.connect('changelog_home', '/{repo_name:.*}/changelog',
143 map.connect('changelog_home', '/{repo_name:.*}/changelog',
144 controller='changelog', conditions=dict(function=check_repo))
144 controller='changelog', conditions=dict(function=check_repo))
145 map.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
145 map.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
146 controller='files', revision='tip', f_path='',
146 controller='files', revision='tip', f_path='',
147 conditions=dict(function=check_repo))
147 conditions=dict(function=check_repo))
148 map.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
148 map.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
149 controller='files', action='diff', revision='tip', f_path='',
149 controller='files', action='diff', revision='tip', f_path='',
150 conditions=dict(function=check_repo))
150 conditions=dict(function=check_repo))
151 map.connect('files_raw_home', '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
151 map.connect('files_rawfile_home', '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
152 controller='files', action='rawfile', revision='tip', f_path='',
152 controller='files', action='rawfile', revision='tip', f_path='',
153 conditions=dict(function=check_repo))
153 conditions=dict(function=check_repo))
154 map.connect('files_raw_home', '/{repo_name:.*}/raw/{revision}/{f_path:.*}',
155 controller='files', action='raw', revision='tip', f_path='',
156 conditions=dict(function=check_repo))
154 map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
157 map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
155 controller='files', action='annotate', revision='tip', f_path='',
158 controller='files', action='annotate', revision='tip', f_path='',
156 conditions=dict(function=check_repo))
159 conditions=dict(function=check_repo))
157 map.connect('files_archive_home', '/{repo_name:.*}/archive/{revision}/{fileformat}',
160 map.connect('files_archive_home', '/{repo_name:.*}/archive/{revision}/{fileformat}',
158 controller='files', action='archivefile', revision='tip',
161 controller='files', action='archivefile', revision='tip',
159 conditions=dict(function=check_repo))
162 conditions=dict(function=check_repo))
160 map.connect('repo_settings_update', '/{repo_name:.*}/settings',
163 map.connect('repo_settings_update', '/{repo_name:.*}/settings',
161 controller='settings', action="update",
164 controller='settings', action="update",
162 conditions=dict(method=["PUT"], function=check_repo))
165 conditions=dict(method=["PUT"], function=check_repo))
163 map.connect('repo_settings_home', '/{repo_name:.*}/settings',
166 map.connect('repo_settings_home', '/{repo_name:.*}/settings',
164 controller='settings', action='index',
167 controller='settings', action='index',
165 conditions=dict(function=check_repo))
168 conditions=dict(function=check_repo))
166
169
167
170
168 return map
171 return map
@@ -1,199 +1,207 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # files controller for pylons
3 # files controller for pylons
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 21, 2010
21 Created on April 21, 2010
22 files controller for pylons
22 files controller for pylons
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from mercurial import archival
25 from mercurial import archival
26 from pylons import request, response, session, tmpl_context as c, url
26 from pylons import request, response, session, tmpl_context as c, url
27 from pylons.controllers.util import redirect
27 from pylons.controllers.util import redirect
28 from pylons_app.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
28 from pylons_app.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
29 from pylons_app.lib.base import BaseController, render
29 from pylons_app.lib.base import BaseController, render
30 from pylons_app.lib.utils import EmptyChangeset
30 from pylons_app.lib.utils import EmptyChangeset
31 from pylons_app.model.hg_model import HgModel
31 from pylons_app.model.hg_model import HgModel
32 from vcs.exceptions import RepositoryError, ChangesetError
32 from vcs.exceptions import RepositoryError, ChangesetError
33 from vcs.nodes import FileNode
33 from vcs.nodes import FileNode
34 from vcs.utils import diffs as differ
34 from vcs.utils import diffs as differ
35 import logging
35 import logging
36 import pylons_app.lib.helpers as h
36 import pylons_app.lib.helpers as h
37 import tempfile
37 import tempfile
38
38
39 log = logging.getLogger(__name__)
39 log = logging.getLogger(__name__)
40
40
41 class FilesController(BaseController):
41 class FilesController(BaseController):
42
42
43 @LoginRequired()
43 @LoginRequired()
44 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
44 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
45 'repository.admin')
45 'repository.admin')
46 def __before__(self):
46 def __before__(self):
47 super(FilesController, self).__before__()
47 super(FilesController, self).__before__()
48 c.file_size_limit = 250 * 1024 #limit of file size to display
48
49
49 def index(self, repo_name, revision, f_path):
50 def index(self, repo_name, revision, f_path):
50 hg_model = HgModel()
51 hg_model = HgModel()
51 c.repo = repo = hg_model.get_repo(c.repo_name)
52 c.repo = repo = hg_model.get_repo(c.repo_name)
52 revision = request.POST.get('at_rev', None) or revision
53 revision = request.POST.get('at_rev', None) or revision
53
54
54 def get_next_rev(cur):
55 def get_next_rev(cur):
55 max_rev = len(c.repo.revisions) - 1
56 max_rev = len(c.repo.revisions) - 1
56 r = cur + 1
57 r = cur + 1
57 if r > max_rev:
58 if r > max_rev:
58 r = max_rev
59 r = max_rev
59 return r
60 return r
60
61
61 def get_prev_rev(cur):
62 def get_prev_rev(cur):
62 r = cur - 1
63 r = cur - 1
63 return r
64 return r
64
65
65 c.f_path = f_path
66 c.f_path = f_path
66
67
67
68
68 try:
69 try:
69 cur_rev = repo.get_changeset(revision).revision
70 cur_rev = repo.get_changeset(revision).revision
70 prev_rev = repo.get_changeset(get_prev_rev(cur_rev)).raw_id
71 prev_rev = repo.get_changeset(get_prev_rev(cur_rev)).raw_id
71 next_rev = repo.get_changeset(get_next_rev(cur_rev)).raw_id
72 next_rev = repo.get_changeset(get_next_rev(cur_rev)).raw_id
72
73
73 c.url_prev = url('files_home', repo_name=c.repo_name,
74 c.url_prev = url('files_home', repo_name=c.repo_name,
74 revision=prev_rev, f_path=f_path)
75 revision=prev_rev, f_path=f_path)
75 c.url_next = url('files_home', repo_name=c.repo_name,
76 c.url_next = url('files_home', repo_name=c.repo_name,
76 revision=next_rev, f_path=f_path)
77 revision=next_rev, f_path=f_path)
77
78
78 c.changeset = repo.get_changeset(revision)
79 c.changeset = repo.get_changeset(revision)
79
80
80
81 c.cur_rev = c.changeset.raw_id
81 c.cur_rev = c.changeset.raw_id
82 c.rev_nr = c.changeset.revision
82 c.rev_nr = c.changeset.revision
83 c.files_list = c.changeset.get_node(f_path)
83 c.files_list = c.changeset.get_node(f_path)
84 c.file_history = self._get_history(repo, c.files_list, f_path)
84 c.file_history = self._get_history(repo, c.files_list, f_path)
85
85
86 except (RepositoryError, ChangesetError):
86 except (RepositoryError, ChangesetError):
87 c.files_list = None
87 c.files_list = None
88
88
89 return render('files/files.html')
89 return render('files/files.html')
90
90
91 def rawfile(self, repo_name, revision, f_path):
91 def rawfile(self, repo_name, revision, f_path):
92 hg_model = HgModel()
92 hg_model = HgModel()
93 c.repo = hg_model.get_repo(c.repo_name)
93 c.repo = hg_model.get_repo(c.repo_name)
94 file_node = c.repo.get_changeset(revision).get_node(f_path)
94 file_node = c.repo.get_changeset(revision).get_node(f_path)
95 response.content_type = file_node.mimetype
95 response.content_type = file_node.mimetype
96 response.content_disposition = 'attachment; filename=%s' \
96 response.content_disposition = 'attachment; filename=%s' \
97 % f_path.split('/')[-1]
97 % f_path.split('/')[-1]
98 return file_node.content
98 return file_node.content
99
100 def raw(self, repo_name, revision, f_path):
101 hg_model = HgModel()
102 c.repo = hg_model.get_repo(c.repo_name)
103 file_node = c.repo.get_changeset(revision).get_node(f_path)
104 response.content_type = 'text/plain'
105
106 return file_node.content
99
107
100 def annotate(self, repo_name, revision, f_path):
108 def annotate(self, repo_name, revision, f_path):
101 hg_model = HgModel()
109 hg_model = HgModel()
102 c.repo = hg_model.get_repo(c.repo_name)
110 c.repo = hg_model.get_repo(c.repo_name)
103 cs = c.repo.get_changeset(revision)
111 cs = c.repo.get_changeset(revision)
104 c.file = cs.get_node(f_path)
112 c.file = cs.get_node(f_path)
105 c.file_msg = cs.get_file_message(f_path)
113 c.file_msg = cs.get_file_message(f_path)
106 c.cur_rev = cs.raw_id
114 c.cur_rev = cs.raw_id
107 c.rev_nr = cs.revision
115 c.rev_nr = cs.revision
108 c.f_path = f_path
116 c.f_path = f_path
109
117
110 return render('files/files_annotate.html')
118 return render('files/files_annotate.html')
111
119
112 def archivefile(self, repo_name, revision, fileformat):
120 def archivefile(self, repo_name, revision, fileformat):
113 archive_specs = {
121 archive_specs = {
114 '.tar.bz2': ('application/x-tar', 'tbz2'),
122 '.tar.bz2': ('application/x-tar', 'tbz2'),
115 '.tar.gz': ('application/x-tar', 'tgz'),
123 '.tar.gz': ('application/x-tar', 'tgz'),
116 '.zip': ('application/zip', 'zip'),
124 '.zip': ('application/zip', 'zip'),
117 }
125 }
118 if not archive_specs.has_key(fileformat):
126 if not archive_specs.has_key(fileformat):
119 return 'Unknown archive type %s' % fileformat
127 return 'Unknown archive type %s' % fileformat
120
128
121 def read_in_chunks(file_object, chunk_size=1024 * 40):
129 def read_in_chunks(file_object, chunk_size=1024 * 40):
122 """Lazy function (generator) to read a file piece by piece.
130 """Lazy function (generator) to read a file piece by piece.
123 Default chunk size: 40k."""
131 Default chunk size: 40k."""
124 while True:
132 while True:
125 data = file_object.read(chunk_size)
133 data = file_object.read(chunk_size)
126 if not data:
134 if not data:
127 break
135 break
128 yield data
136 yield data
129
137
130 archive = tempfile.TemporaryFile()
138 archive = tempfile.TemporaryFile()
131 repo = HgModel().get_repo(repo_name).repo
139 repo = HgModel().get_repo(repo_name).repo
132 fname = '%s-%s%s' % (repo_name, revision, fileformat)
140 fname = '%s-%s%s' % (repo_name, revision, fileformat)
133 archival.archive(repo, archive, revision, archive_specs[fileformat][1],
141 archival.archive(repo, archive, revision, archive_specs[fileformat][1],
134 prefix='%s-%s' % (repo_name, revision))
142 prefix='%s-%s' % (repo_name, revision))
135 response.content_type = archive_specs[fileformat][0]
143 response.content_type = archive_specs[fileformat][0]
136 response.content_disposition = 'attachment; filename=%s' % fname
144 response.content_disposition = 'attachment; filename=%s' % fname
137 archive.seek(0)
145 archive.seek(0)
138 return read_in_chunks(archive)
146 return read_in_chunks(archive)
139
147
140 def diff(self, repo_name, f_path):
148 def diff(self, repo_name, f_path):
141 hg_model = HgModel()
149 hg_model = HgModel()
142 diff1 = request.GET.get('diff1')
150 diff1 = request.GET.get('diff1')
143 diff2 = request.GET.get('diff2')
151 diff2 = request.GET.get('diff2')
144 c.action = request.GET.get('diff')
152 c.action = request.GET.get('diff')
145 c.no_changes = diff1 == diff2
153 c.no_changes = diff1 == diff2
146 c.f_path = f_path
154 c.f_path = f_path
147 c.repo = hg_model.get_repo(c.repo_name)
155 c.repo = hg_model.get_repo(c.repo_name)
148
156
149 try:
157 try:
150 if diff1 not in ['', None, 'None', '0' * 12]:
158 if diff1 not in ['', None, 'None', '0' * 12]:
151 c.changeset_1 = c.repo.get_changeset(diff1)
159 c.changeset_1 = c.repo.get_changeset(diff1)
152 node1 = c.changeset_1.get_node(f_path)
160 node1 = c.changeset_1.get_node(f_path)
153 else:
161 else:
154 c.changeset_1 = EmptyChangeset()
162 c.changeset_1 = EmptyChangeset()
155 node1 = FileNode('.', '')
163 node1 = FileNode('.', '')
156 if diff2 not in ['', None, 'None', '0' * 12]:
164 if diff2 not in ['', None, 'None', '0' * 12]:
157 c.changeset_2 = c.repo.get_changeset(diff2)
165 c.changeset_2 = c.repo.get_changeset(diff2)
158 node2 = c.changeset_2.get_node(f_path)
166 node2 = c.changeset_2.get_node(f_path)
159 else:
167 else:
160 c.changeset_2 = EmptyChangeset()
168 c.changeset_2 = EmptyChangeset()
161 node2 = FileNode('.', '')
169 node2 = FileNode('.', '')
162 except RepositoryError:
170 except RepositoryError:
163 return redirect(url('files_home',
171 return redirect(url('files_home',
164 repo_name=c.repo_name, f_path=f_path))
172 repo_name=c.repo_name, f_path=f_path))
165
173
166 c.diff1 = 'r%s:%s' % (c.changeset_1.revision, c.changeset_1.raw_id)
174 c.diff1 = 'r%s:%s' % (c.changeset_1.revision, c.changeset_1.raw_id)
167 c.diff2 = 'r%s:%s' % (c.changeset_2.revision, c.changeset_2.raw_id)
175 c.diff2 = 'r%s:%s' % (c.changeset_2.revision, c.changeset_2.raw_id)
168 f_udiff = differ.get_udiff(node1, node2)
176 f_udiff = differ.get_udiff(node1, node2)
169
177
170 diff = differ.DiffProcessor(f_udiff)
178 diff = differ.DiffProcessor(f_udiff)
171
179
172 if c.action == 'download':
180 if c.action == 'download':
173 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
181 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
174 response.content_type = 'text/plain'
182 response.content_type = 'text/plain'
175 response.content_disposition = 'attachment; filename=%s' \
183 response.content_disposition = 'attachment; filename=%s' \
176 % diff_name
184 % diff_name
177 return diff.raw_diff()
185 return diff.raw_diff()
178
186
179 elif c.action == 'raw':
187 elif c.action == 'raw':
180 c.cur_diff = '<pre class="raw">%s</pre>' % h.escape(diff.raw_diff())
188 c.cur_diff = '<pre class="raw">%s</pre>' % h.escape(diff.raw_diff())
181 elif c.action == 'diff':
189 elif c.action == 'diff':
182 c.cur_diff = diff.as_html()
190 c.cur_diff = diff.as_html()
183 else:
191 else:
184 #default option
192 #default option
185 c.cur_diff = diff.as_html()
193 c.cur_diff = diff.as_html()
186
194
187 if not c.cur_diff: c.no_changes = True
195 if not c.cur_diff: c.no_changes = True
188 return render('files/file_diff.html')
196 return render('files/file_diff.html')
189
197
190 def _get_history(self, repo, node, f_path):
198 def _get_history(self, repo, node, f_path):
191 from vcs.nodes import NodeKind
199 from vcs.nodes import NodeKind
192 if not node.kind is NodeKind.FILE:
200 if not node.kind is NodeKind.FILE:
193 return []
201 return []
194 changesets = node.history
202 changesets = node.history
195 hist_l = []
203 hist_l = []
196 for chs in changesets:
204 for chs in changesets:
197 n_desc = 'r%s:%s' % (chs.revision, chs._short)
205 n_desc = 'r%s:%s' % (chs.revision, chs._short)
198 hist_l.append((chs._short, n_desc,))
206 hist_l.append((chs._short, n_desc,))
199 return hist_l
207 return hist_l
@@ -1,52 +1,59 b''
1 <%inherit file="/base/base.html"/>
1 <%inherit file="/base/base.html"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ${_('File annotate')}
4 ${_('File annotate')}
5 </%def>
5 </%def>
6
6
7 <%def name="breadcrumbs_links()">
7 <%def name="breadcrumbs_links()">
8 ${h.link_to(u'Home',h.url('/'))}
8 ${h.link_to(u'Home',h.url('/'))}
9 &raquo;
9 &raquo;
10 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
10 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
11 &raquo;
11 &raquo;
12 ${_('annotate')} @ R${c.rev_nr}:${c.cur_rev}
12 ${_('annotate')} @ R${c.rev_nr}:${c.cur_rev}
13 </%def>
13 </%def>
14
14
15 <%def name="page_nav()">
15 <%def name="page_nav()">
16 ${self.menu('files')}
16 ${self.menu('files')}
17 </%def>
17 </%def>
18 <%def name="main()">
18 <%def name="main()">
19 <div class="box">
19 <div class="box">
20 <!-- box / title -->
20 <!-- box / title -->
21 <div class="title">
21 <div class="title">
22 ${self.breadcrumbs()}
22 ${self.breadcrumbs()}
23 </div>
23 </div>
24 <div class="table">
24 <div class="table">
25 <div id="files_data">
25 <div id="files_data">
26 <h2>${_('Location')}: ${h.files_breadcrumbs(c.repo_name,c.cur_rev,c.file.path)}</h2>
26 <h3 class="files_location">${_('Location')}: ${h.files_breadcrumbs(c.repo_name,c.cur_rev,c.file.path)}</h3>
27 <dl class="overview">
27 <dl class="overview">
28 <dt>${_('Last revision')}</dt>
28 <dt>${_('Last revision')}</dt>
29 <dd>${h.link_to("r%s:%s" % (c.file.last_changeset.revision,c.file.last_changeset._short),
29 <dd>${h.link_to("r%s:%s" % (c.file.last_changeset.revision,c.file.last_changeset._short),
30 h.url('files_annotate_home',repo_name=c.repo_name,revision=c.file.last_changeset._short,f_path=c.f_path))} </dd>
30 h.url('files_annotate_home',repo_name=c.repo_name,revision=c.file.last_changeset._short,f_path=c.f_path))} </dd>
31 <dt>${_('Size')}</dt>
31 <dt>${_('Size')}</dt>
32 <dd>${h.format_byte_size(c.file.size,binary=True)}</dd>
32 <dd>${h.format_byte_size(c.file.size,binary=True)}</dd>
33 <dt>${_('Options')}</dt>
33 <dt>${_('Options')}</dt>
34 <dd>${h.link_to(_('show source'),
34 <dd>${h.link_to(_('show source'),
35 h.url('files_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}
35 h.url('files_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}
36 / ${h.link_to(_('show as raw'),
37 h.url('files_raw_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}
36 / ${h.link_to(_('download as raw'),
38 / ${h.link_to(_('download as raw'),
37 h.url('files_raw_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}
39 h.url('files_rawfile_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}
38 </dd>
40 </dd>
39 </dl>
41 </dl>
40 <div id="body" class="codeblock">
42 <div id="body" class="codeblock">
41 <div class="code-header">
43 <div class="code-header">
42 <div class="revision">${c.file.name}@r${c.file.last_changeset.revision}:${c.file.last_changeset._short}</div>
44 <div class="revision">${c.file.name}@r${c.file.last_changeset.revision}:${c.file.last_changeset._short}</div>
43 <div class="commit">"${c.file_msg}"</div>
45 <div class="commit">"${c.file_msg}"</div>
44 </div>
46 </div>
45 <div class="code-body">
47 <div class="code-body">
46 ${h.pygmentize_annotation(c.file,linenos=True,anchorlinenos=True,lineanchors='S',cssclass="code-highlight")}
48 % if c.file.size < c.file_size_limit:
49 ${h.pygmentize_annotation(c.file,linenos=True,anchorlinenos=True,lineanchors='S',cssclass="code-highlight")}
50 %else:
51 ${_('File is to big to display')} ${h.link_to(_('show as raw'),
52 h.url('files_raw_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}
53 %endif
47 </div>
54 </div>
48 </div>
55 </div>
49 </div>
56 </div>
50 </div>
57 </div>
51 </div>
58 </div>
52 </%def> No newline at end of file
59 </%def>
@@ -1,48 +1,55 b''
1 <dl>
1 <dl>
2 <dt>${_('Last revision')}</dt>
2 <dt>${_('Last revision')}</dt>
3 <dd>
3 <dd>
4 ${h.link_to("r%s:%s" % (c.files_list.last_changeset.revision,c.files_list.last_changeset._short),
4 ${h.link_to("r%s:%s" % (c.files_list.last_changeset.revision,c.files_list.last_changeset._short),
5 h.url('files_home',repo_name=c.repo_name,revision=c.files_list.last_changeset._short,f_path=c.f_path))}
5 h.url('files_home',repo_name=c.repo_name,revision=c.files_list.last_changeset._short,f_path=c.f_path))}
6 </dd>
6 </dd>
7 <dt>${_('Size')}</dt>
7 <dt>${_('Size')}</dt>
8 <dd>${h.format_byte_size(c.files_list.size,binary=True)}</dd>
8 <dd>${h.format_byte_size(c.files_list.size,binary=True)}</dd>
9 <dt>${_('Options')}</dt>
9 <dt>${_('Options')}</dt>
10 <dd>${h.link_to(_('show annotation'),
10 <dd>${h.link_to(_('show annotation'),
11 h.url('files_annotate_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}
11 h.url('files_annotate_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}
12 / ${h.link_to(_('show as raw'),
13 h.url('files_raw_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}
12 / ${h.link_to(_('download as raw'),
14 / ${h.link_to(_('download as raw'),
13 h.url('files_raw_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}
15 h.url('files_rawfile_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}
14 </dd>
16 </dd>
15 <dt>${_('History')}</dt>
17 <dt>${_('History')}</dt>
16 <dd>
18 <dd>
17 <div>
19 <div>
18 ${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')}
20 ${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')}
19 ${h.hidden('diff2',c.files_list.last_changeset._short)}
21 ${h.hidden('diff2',c.files_list.last_changeset._short)}
20 ${h.select('diff1',c.files_list.last_changeset._short,c.file_history)}
22 ${h.select('diff1',c.files_list.last_changeset._short,c.file_history)}
21 ${h.submit('diff','diff to revision',class_="ui-button ui-widget ui-state-default ui-corner-all")}
23 ${h.submit('diff','diff to revision',class_="ui-button ui-widget ui-state-default ui-corner-all")}
22 ${h.submit('show_rev','show at revision',class_="ui-button ui-widget ui-state-default ui-corner-all")}
24 ${h.submit('show_rev','show at revision',class_="ui-button ui-widget ui-state-default ui-corner-all")}
23 ${h.end_form()}
25 ${h.end_form()}
24 </div>
26 </div>
25 </dd>
27 </dd>
26 </dl>
28 </dl>
27
29
28
30
29 <div id="body" class="codeblock">
31 <div id="body" class="codeblock">
30 <div class="code-header">
32 <div class="code-header">
31 <div class="revision">${c.files_list.name}@r${c.files_list.last_changeset.revision}:${c.files_list.last_changeset._short}</div>
33 <div class="revision">${c.files_list.name}@r${c.files_list.last_changeset.revision}:${c.files_list.last_changeset._short}</div>
32 <div class="commit">"${c.files_list.last_changeset.message}"</div>
34 <div class="commit">"${c.files_list.last_changeset.message}"</div>
33 </div>
35 </div>
34 <div class="code-body">
36 <div class="code-body">
35 ${h.pygmentize(c.files_list,linenos=True,anchorlinenos=True,lineanchors='S',cssclass="code-highlight")}
37 % if c.files_list.size < c.file_size_limit:
38 ${h.pygmentize(c.files_list,linenos=True,anchorlinenos=True,lineanchors='S',cssclass="code-highlight")}
39 %else:
40 ${_('File is to big to display')} ${h.link_to(_('show as raw'),
41 h.url('files_raw_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}
42 %endif
36 </div>
43 </div>
37 </div>
44 </div>
38
45
39 <script type="text/javascript">
46 <script type="text/javascript">
40 YAHOO.util.Event.onDOMReady(function(){
47 YAHOO.util.Event.onDOMReady(function(){
41 YAHOO.util.Event.addListener('show_rev','click',function(e){
48 YAHOO.util.Event.addListener('show_rev','click',function(e){
42 YAHOO.util.Event.preventDefault(e);
49 YAHOO.util.Event.preventDefault(e);
43 var cs = YAHOO.util.Dom.get('diff1').value;
50 var cs = YAHOO.util.Dom.get('diff1').value;
44 var url = "${h.url('files_home',repo_name=c.repo_name,revision='__CS__',f_path=c.f_path)}".replace('__CS__',cs);
51 var url = "${h.url('files_home',repo_name=c.repo_name,revision='__CS__',f_path=c.f_path)}".replace('__CS__',cs);
45 window.location = url;
52 window.location = url;
46 });
53 });
47 });
54 });
48 </script> No newline at end of file
55 </script>
General Comments 0
You need to be logged in to leave comments. Login now