##// END OF EJS Templates
fixes issue #436 git push error
marcink -
r2236:37c143aa beta
parent child Browse files
Show More
@@ -1,190 +1,190 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.hooks
3 rhodecode.lib.hooks
4 ~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~
5
5
6 Hooks runned by rhodecode
6 Hooks runned by rhodecode
7
7
8 :created_on: Aug 6, 2010
8 :created_on: Aug 6, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 import os
25 import os
26 import sys
26 import sys
27
27
28 from mercurial.scmutil import revrange
28 from mercurial.scmutil import revrange
29 from mercurial.node import nullrev
29 from mercurial.node import nullrev
30 from rhodecode import EXTENSIONS
30 from rhodecode import EXTENSIONS
31 from rhodecode.lib import helpers as h
31 from rhodecode.lib import helpers as h
32 from rhodecode.lib.utils import action_logger
32 from rhodecode.lib.utils import action_logger
33 from inspect import isfunction
33 from inspect import isfunction
34
34
35
35
36 def _get_scm_size(alias, root_path):
36 def _get_scm_size(alias, root_path):
37
37
38 if not alias.startswith('.'):
38 if not alias.startswith('.'):
39 alias += '.'
39 alias += '.'
40
40
41 size_scm, size_root = 0, 0
41 size_scm, size_root = 0, 0
42 for path, dirs, files in os.walk(root_path):
42 for path, dirs, files in os.walk(root_path):
43 if path.find(alias) != -1:
43 if path.find(alias) != -1:
44 for f in files:
44 for f in files:
45 try:
45 try:
46 size_scm += os.path.getsize(os.path.join(path, f))
46 size_scm += os.path.getsize(os.path.join(path, f))
47 except OSError:
47 except OSError:
48 pass
48 pass
49 else:
49 else:
50 for f in files:
50 for f in files:
51 try:
51 try:
52 size_root += os.path.getsize(os.path.join(path, f))
52 size_root += os.path.getsize(os.path.join(path, f))
53 except OSError:
53 except OSError:
54 pass
54 pass
55
55
56 size_scm_f = h.format_byte_size(size_scm)
56 size_scm_f = h.format_byte_size(size_scm)
57 size_root_f = h.format_byte_size(size_root)
57 size_root_f = h.format_byte_size(size_root)
58 size_total_f = h.format_byte_size(size_root + size_scm)
58 size_total_f = h.format_byte_size(size_root + size_scm)
59
59
60 return size_scm_f, size_root_f, size_total_f
60 return size_scm_f, size_root_f, size_total_f
61
61
62
62
63 def repo_size(ui, repo, hooktype=None, **kwargs):
63 def repo_size(ui, repo, hooktype=None, **kwargs):
64 """
64 """
65 Presents size of repository after push
65 Presents size of repository after push
66
66
67 :param ui:
67 :param ui:
68 :param repo:
68 :param repo:
69 :param hooktype:
69 :param hooktype:
70 """
70 """
71
71
72 size_hg_f, size_root_f, size_total_f = _get_scm_size('.hg', repo.root)
72 size_hg_f, size_root_f, size_total_f = _get_scm_size('.hg', repo.root)
73
73
74 last_cs = repo[len(repo) - 1]
74 last_cs = repo[len(repo) - 1]
75
75
76 msg = ('Repository size .hg:%s repo:%s total:%s\n'
76 msg = ('Repository size .hg:%s repo:%s total:%s\n'
77 'Last revision is now r%s:%s\n') % (
77 'Last revision is now r%s:%s\n') % (
78 size_hg_f, size_root_f, size_total_f, last_cs.rev(), last_cs.hex()[:12]
78 size_hg_f, size_root_f, size_total_f, last_cs.rev(), last_cs.hex()[:12]
79 )
79 )
80
80
81 sys.stdout.write(msg)
81 sys.stdout.write(msg)
82
82
83
83
84 def log_pull_action(ui, repo, **kwargs):
84 def log_pull_action(ui, repo, **kwargs):
85 """
85 """
86 Logs user last pull action
86 Logs user last pull action
87
87
88 :param ui:
88 :param ui:
89 :param repo:
89 :param repo:
90 """
90 """
91
91
92 extras = dict(repo.ui.configitems('rhodecode_extras'))
92 extras = dict(repo.ui.configitems('rhodecode_extras'))
93 username = extras['username']
93 username = extras['username']
94 repository = extras['repository']
94 repository = extras['repository']
95 scm = extras['scm']
95 scm = extras['scm']
96 action = 'pull'
96 action = 'pull'
97
97
98 action_logger(username, action, repository, extras['ip'], commit=True)
98 action_logger(username, action, repository, extras['ip'], commit=True)
99 # extension hook call
99 # extension hook call
100 callback = getattr(EXTENSIONS, 'PULL_HOOK', None)
100 callback = getattr(EXTENSIONS, 'PULL_HOOK', None)
101
101
102 if isfunction(callback):
102 if isfunction(callback):
103 kw = {}
103 kw = {}
104 kw.update(extras)
104 kw.update(extras)
105 callback(**kw)
105 callback(**kw)
106 return 0
106 return 0
107
107
108
108
109 def log_push_action(ui, repo, **kwargs):
109 def log_push_action(ui, repo, **kwargs):
110 """
110 """
111 Maps user last push action to new changeset id, from mercurial
111 Maps user last push action to new changeset id, from mercurial
112
112
113 :param ui:
113 :param ui:
114 :param repo:
114 :param repo: repo object containing the `ui` object
115 """
115 """
116
116
117 extras = dict(repo.ui.configitems('rhodecode_extras'))
117 extras = dict(repo.ui.configitems('rhodecode_extras'))
118 username = extras['username']
118 username = extras['username']
119 repository = extras['repository']
119 repository = extras['repository']
120 action = extras['action'] + ':%s'
120 action = extras['action'] + ':%s'
121 scm = extras['scm']
121 scm = extras['scm']
122
122
123 if scm == 'hg':
123 if scm == 'hg':
124 node = kwargs['node']
124 node = kwargs['node']
125
125
126 def get_revs(repo, rev_opt):
126 def get_revs(repo, rev_opt):
127 if rev_opt:
127 if rev_opt:
128 revs = revrange(repo, rev_opt)
128 revs = revrange(repo, rev_opt)
129
129
130 if len(revs) == 0:
130 if len(revs) == 0:
131 return (nullrev, nullrev)
131 return (nullrev, nullrev)
132 return (max(revs), min(revs))
132 return (max(revs), min(revs))
133 else:
133 else:
134 return (len(repo) - 1, 0)
134 return (len(repo) - 1, 0)
135
135
136 stop, start = get_revs(repo, [node + ':'])
136 stop, start = get_revs(repo, [node + ':'])
137
137
138 revs = (str(repo[r]) for r in xrange(start, stop + 1))
138 revs = (str(repo[r]) for r in xrange(start, stop + 1))
139 elif scm == 'git':
139 elif scm == 'git':
140 revs = []
140 revs = []
141
141
142 action = action % ','.join(revs)
142 action = action % ','.join(revs)
143
143
144 action_logger(username, action, repository, extras['ip'], commit=True)
144 action_logger(username, action, repository, extras['ip'], commit=True)
145
145
146 # extension hook call
146 # extension hook call
147 callback = getattr(EXTENSIONS, 'PUSH_HOOK', None)
147 callback = getattr(EXTENSIONS, 'PUSH_HOOK', None)
148 if isfunction(callback):
148 if isfunction(callback):
149 kw = {'pushed_revs': revs}
149 kw = {'pushed_revs': revs}
150 kw.update(extras)
150 kw.update(extras)
151 callback(**kw)
151 callback(**kw)
152 return 0
152 return 0
153
153
154
154
155 def log_create_repository(repository_dict, created_by, **kwargs):
155 def log_create_repository(repository_dict, created_by, **kwargs):
156 """
156 """
157 Post create repository Hook. This is a dummy function for admins to re-use
157 Post create repository Hook. This is a dummy function for admins to re-use
158 if needed. It's taken from rhodecode-extensions module and executed
158 if needed. It's taken from rhodecode-extensions module and executed
159 if present
159 if present
160
160
161 :param repository: dict dump of repository object
161 :param repository: dict dump of repository object
162 :param created_by: username who created repository
162 :param created_by: username who created repository
163 :param created_date: date of creation
163 :param created_date: date of creation
164
164
165 available keys of repository_dict:
165 available keys of repository_dict:
166
166
167 'repo_type',
167 'repo_type',
168 'description',
168 'description',
169 'private',
169 'private',
170 'created_on',
170 'created_on',
171 'enable_downloads',
171 'enable_downloads',
172 'repo_id',
172 'repo_id',
173 'user_id',
173 'user_id',
174 'enable_statistics',
174 'enable_statistics',
175 'clone_uri',
175 'clone_uri',
176 'fork_id',
176 'fork_id',
177 'group_id',
177 'group_id',
178 'repo_name'
178 'repo_name'
179
179
180 """
180 """
181
181
182 callback = getattr(EXTENSIONS, 'CREATE_REPO_HOOK', None)
182 callback = getattr(EXTENSIONS, 'CREATE_REPO_HOOK', None)
183 if isfunction(callback):
183 if isfunction(callback):
184 kw = {}
184 kw = {}
185 kw.update(repository_dict)
185 kw.update(repository_dict)
186 kw.update({'created_by': created_by})
186 kw.update({'created_by': created_by})
187 kw.update(kwargs)
187 kw.update(kwargs)
188 return callback(**kw)
188 return callback(**kw)
189
189
190 return 0
190 return 0
@@ -1,300 +1,300 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.middleware.simplegit
3 rhodecode.lib.middleware.simplegit
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 SimpleGit middleware for handling git protocol request (push/clone etc.)
6 SimpleGit middleware for handling git protocol request (push/clone etc.)
7 It's implemented with basic auth function
7 It's implemented with basic auth function
8
8
9 :created_on: Apr 28, 2010
9 :created_on: Apr 28, 2010
10 :author: marcink
10 :author: marcink
11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 :license: GPLv3, see COPYING for more details.
12 :license: GPLv3, see COPYING for more details.
13 """
13 """
14 # This program is free software: you can redistribute it and/or modify
14 # This program is free software: you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation, either version 3 of the License, or
16 # the Free Software Foundation, either version 3 of the License, or
17 # (at your option) any later version.
17 # (at your option) any later version.
18 #
18 #
19 # This program is distributed in the hope that it will be useful,
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
22 # GNU General Public License for more details.
23 #
23 #
24 # You should have received a copy of the GNU General Public License
24 # You should have received a copy of the GNU General Public License
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26
26
27 import os
27 import os
28 import re
28 import re
29 import logging
29 import logging
30 import traceback
30 import traceback
31
31
32 from dulwich import server as dulserver
32 from dulwich import server as dulserver
33
33
34
34
35 class SimpleGitUploadPackHandler(dulserver.UploadPackHandler):
35 class SimpleGitUploadPackHandler(dulserver.UploadPackHandler):
36
36
37 def handle(self):
37 def handle(self):
38 write = lambda x: self.proto.write_sideband(1, x)
38 write = lambda x: self.proto.write_sideband(1, x)
39
39
40 graph_walker = dulserver.ProtocolGraphWalker(self,
40 graph_walker = dulserver.ProtocolGraphWalker(self,
41 self.repo.object_store,
41 self.repo.object_store,
42 self.repo.get_peeled)
42 self.repo.get_peeled)
43 objects_iter = self.repo.fetch_objects(
43 objects_iter = self.repo.fetch_objects(
44 graph_walker.determine_wants, graph_walker, self.progress,
44 graph_walker.determine_wants, graph_walker, self.progress,
45 get_tagged=self.get_tagged)
45 get_tagged=self.get_tagged)
46
46
47 # Did the process short-circuit (e.g. in a stateless RPC call)? Note
47 # Did the process short-circuit (e.g. in a stateless RPC call)? Note
48 # that the client still expects a 0-object pack in most cases.
48 # that the client still expects a 0-object pack in most cases.
49 if objects_iter is None:
49 if objects_iter is None:
50 return
50 return
51
51
52 self.progress("counting objects: %d, done.\n" % len(objects_iter))
52 self.progress("counting objects: %d, done.\n" % len(objects_iter))
53 dulserver.write_pack_objects(dulserver.ProtocolFile(None, write),
53 dulserver.write_pack_objects(dulserver.ProtocolFile(None, write),
54 objects_iter)
54 objects_iter)
55 messages = []
55 messages = []
56 messages.append('thank you for using rhodecode')
56 messages.append('thank you for using rhodecode')
57
57
58 for msg in messages:
58 for msg in messages:
59 self.progress(msg + "\n")
59 self.progress(msg + "\n")
60 # we are done
60 # we are done
61 self.proto.write("0000")
61 self.proto.write("0000")
62
62
63
63
64 dulserver.DEFAULT_HANDLERS = {
64 dulserver.DEFAULT_HANDLERS = {
65 'git-upload-pack': SimpleGitUploadPackHandler,
65 'git-upload-pack': SimpleGitUploadPackHandler,
66 'git-receive-pack': dulserver.ReceivePackHandler,
66 'git-receive-pack': dulserver.ReceivePackHandler,
67 }
67 }
68
68
69 from dulwich.repo import Repo
69 from dulwich.repo import Repo
70 from dulwich.web import make_wsgi_chain
70 from dulwich.web import make_wsgi_chain
71
71
72 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
72 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
73
73
74 from rhodecode.lib.utils2 import safe_str
74 from rhodecode.lib.utils2 import safe_str
75 from rhodecode.lib.base import BaseVCSController
75 from rhodecode.lib.base import BaseVCSController
76 from rhodecode.lib.auth import get_container_username
76 from rhodecode.lib.auth import get_container_username
77 from rhodecode.lib.utils import is_valid_repo, make_ui
77 from rhodecode.lib.utils import is_valid_repo, make_ui
78 from rhodecode.model.db import User
78 from rhodecode.model.db import User
79
79
80 from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError
80 from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError
81
81
82 log = logging.getLogger(__name__)
82 log = logging.getLogger(__name__)
83
83
84
84
85 GIT_PROTO_PAT = re.compile(r'^/(.+)/(info/refs|git-upload-pack|git-receive-pack)')
85 GIT_PROTO_PAT = re.compile(r'^/(.+)/(info/refs|git-upload-pack|git-receive-pack)')
86
86
87
87
88 def is_git(environ):
88 def is_git(environ):
89 path_info = environ['PATH_INFO']
89 path_info = environ['PATH_INFO']
90 isgit_path = GIT_PROTO_PAT.match(path_info)
90 isgit_path = GIT_PROTO_PAT.match(path_info)
91 log.debug('pathinfo: %s detected as GIT %s' % (
91 log.debug('pathinfo: %s detected as GIT %s' % (
92 path_info, isgit_path != None)
92 path_info, isgit_path != None)
93 )
93 )
94 return isgit_path
94 return isgit_path
95
95
96
96
97 class SimpleGit(BaseVCSController):
97 class SimpleGit(BaseVCSController):
98
98
99 def _handle_request(self, environ, start_response):
99 def _handle_request(self, environ, start_response):
100
100
101 if not is_git(environ):
101 if not is_git(environ):
102 return self.application(environ, start_response)
102 return self.application(environ, start_response)
103
103
104 ipaddr = self._get_ip_addr(environ)
104 ipaddr = self._get_ip_addr(environ)
105 username = None
105 username = None
106 self._git_first_op = False
106 self._git_first_op = False
107 # skip passing error to error controller
107 # skip passing error to error controller
108 environ['pylons.status_code_redirect'] = True
108 environ['pylons.status_code_redirect'] = True
109
109
110 #======================================================================
110 #======================================================================
111 # EXTRACT REPOSITORY NAME FROM ENV
111 # EXTRACT REPOSITORY NAME FROM ENV
112 #======================================================================
112 #======================================================================
113 try:
113 try:
114 repo_name = self.__get_repository(environ)
114 repo_name = self.__get_repository(environ)
115 log.debug('Extracted repo name is %s' % repo_name)
115 log.debug('Extracted repo name is %s' % repo_name)
116 except:
116 except:
117 return HTTPInternalServerError()(environ, start_response)
117 return HTTPInternalServerError()(environ, start_response)
118
118
119 # quick check if that dir exists...
119 # quick check if that dir exists...
120 if is_valid_repo(repo_name, self.basepath) is False:
120 if is_valid_repo(repo_name, self.basepath) is False:
121 return HTTPNotFound()(environ, start_response)
121 return HTTPNotFound()(environ, start_response)
122
122
123 #======================================================================
123 #======================================================================
124 # GET ACTION PULL or PUSH
124 # GET ACTION PULL or PUSH
125 #======================================================================
125 #======================================================================
126 action = self.__get_action(environ)
126 action = self.__get_action(environ)
127
127
128 #======================================================================
128 #======================================================================
129 # CHECK ANONYMOUS PERMISSION
129 # CHECK ANONYMOUS PERMISSION
130 #======================================================================
130 #======================================================================
131 if action in ['pull', 'push']:
131 if action in ['pull', 'push']:
132 anonymous_user = self.__get_user('default')
132 anonymous_user = self.__get_user('default')
133 username = anonymous_user.username
133 username = anonymous_user.username
134 anonymous_perm = self._check_permission(action, anonymous_user,
134 anonymous_perm = self._check_permission(action, anonymous_user,
135 repo_name)
135 repo_name)
136
136
137 if anonymous_perm is not True or anonymous_user.active is False:
137 if anonymous_perm is not True or anonymous_user.active is False:
138 if anonymous_perm is not True:
138 if anonymous_perm is not True:
139 log.debug('Not enough credentials to access this '
139 log.debug('Not enough credentials to access this '
140 'repository as anonymous user')
140 'repository as anonymous user')
141 if anonymous_user.active is False:
141 if anonymous_user.active is False:
142 log.debug('Anonymous access is disabled, running '
142 log.debug('Anonymous access is disabled, running '
143 'authentication')
143 'authentication')
144 #==============================================================
144 #==============================================================
145 # DEFAULT PERM FAILED OR ANONYMOUS ACCESS IS DISABLED SO WE
145 # DEFAULT PERM FAILED OR ANONYMOUS ACCESS IS DISABLED SO WE
146 # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS
146 # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS
147 #==============================================================
147 #==============================================================
148
148
149 # Attempting to retrieve username from the container
149 # Attempting to retrieve username from the container
150 username = get_container_username(environ, self.config)
150 username = get_container_username(environ, self.config)
151
151
152 # If not authenticated by the container, running basic auth
152 # If not authenticated by the container, running basic auth
153 if not username:
153 if not username:
154 self.authenticate.realm = \
154 self.authenticate.realm = \
155 safe_str(self.config['rhodecode_realm'])
155 safe_str(self.config['rhodecode_realm'])
156 result = self.authenticate(environ)
156 result = self.authenticate(environ)
157 if isinstance(result, str):
157 if isinstance(result, str):
158 AUTH_TYPE.update(environ, 'basic')
158 AUTH_TYPE.update(environ, 'basic')
159 REMOTE_USER.update(environ, result)
159 REMOTE_USER.update(environ, result)
160 username = result
160 username = result
161 else:
161 else:
162 return result.wsgi_application(environ, start_response)
162 return result.wsgi_application(environ, start_response)
163
163
164 #==============================================================
164 #==============================================================
165 # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME
165 # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME
166 #==============================================================
166 #==============================================================
167 if action in ['pull', 'push']:
167 if action in ['pull', 'push']:
168 try:
168 try:
169 user = self.__get_user(username)
169 user = self.__get_user(username)
170 if user is None or not user.active:
170 if user is None or not user.active:
171 return HTTPForbidden()(environ, start_response)
171 return HTTPForbidden()(environ, start_response)
172 username = user.username
172 username = user.username
173 except:
173 except:
174 log.error(traceback.format_exc())
174 log.error(traceback.format_exc())
175 return HTTPInternalServerError()(environ,
175 return HTTPInternalServerError()(environ,
176 start_response)
176 start_response)
177
177
178 #check permissions for this repository
178 #check permissions for this repository
179 perm = self._check_permission(action, user, repo_name)
179 perm = self._check_permission(action, user, repo_name)
180 if perm is not True:
180 if perm is not True:
181 return HTTPForbidden()(environ, start_response)
181 return HTTPForbidden()(environ, start_response)
182 extras = {
182 extras = {
183 'ip': ipaddr,
183 'ip': ipaddr,
184 'username': username,
184 'username': username,
185 'action': action,
185 'action': action,
186 'repository': repo_name,
186 'repository': repo_name,
187 'scm': 'git',
187 'scm': 'git',
188 }
188 }
189
189
190 #===================================================================
190 #===================================================================
191 # GIT REQUEST HANDLING
191 # GIT REQUEST HANDLING
192 #===================================================================
192 #===================================================================
193 repo_path = os.path.join(safe_str(self.basepath), safe_str(repo_name))
193 repo_path = os.path.join(safe_str(self.basepath), safe_str(repo_name))
194 log.debug('Repository path is %s' % repo_path)
194 log.debug('Repository path is %s' % repo_path)
195
195
196 baseui = make_ui('db')
196 baseui = make_ui('db')
197 self.__inject_extras(repo_path, baseui, extras)
197 self.__inject_extras(repo_path, baseui, extras)
198
198
199
199
200 try:
200 try:
201 # invalidate cache on push
201 # invalidate cache on push
202 if action == 'push':
202 if action == 'push':
203 self._invalidate_cache(repo_name)
203 self._invalidate_cache(repo_name)
204 self._handle_githooks(action, baseui, environ)
204 self._handle_githooks(repo_name, action, baseui, environ)
205
205
206 log.info('%s action on GIT repo "%s"' % (action, repo_name))
206 log.info('%s action on GIT repo "%s"' % (action, repo_name))
207 app = self.__make_app(repo_name, repo_path)
207 app = self.__make_app(repo_name, repo_path)
208 return app(environ, start_response)
208 return app(environ, start_response)
209 except Exception:
209 except Exception:
210 log.error(traceback.format_exc())
210 log.error(traceback.format_exc())
211 return HTTPInternalServerError()(environ, start_response)
211 return HTTPInternalServerError()(environ, start_response)
212
212
213 def __make_app(self, repo_name, repo_path):
213 def __make_app(self, repo_name, repo_path):
214 """
214 """
215 Make an wsgi application using dulserver
215 Make an wsgi application using dulserver
216
216
217 :param repo_name: name of the repository
217 :param repo_name: name of the repository
218 :param repo_path: full path to the repository
218 :param repo_path: full path to the repository
219 """
219 """
220 _d = {'/' + repo_name: Repo(repo_path)}
220 _d = {'/' + repo_name: Repo(repo_path)}
221 backend = dulserver.DictBackend(_d)
221 backend = dulserver.DictBackend(_d)
222 gitserve = make_wsgi_chain(backend)
222 gitserve = make_wsgi_chain(backend)
223
223
224 return gitserve
224 return gitserve
225
225
226 def __get_repository(self, environ):
226 def __get_repository(self, environ):
227 """
227 """
228 Get's repository name out of PATH_INFO header
228 Get's repository name out of PATH_INFO header
229
229
230 :param environ: environ where PATH_INFO is stored
230 :param environ: environ where PATH_INFO is stored
231 """
231 """
232 try:
232 try:
233 environ['PATH_INFO'] = self._get_by_id(environ['PATH_INFO'])
233 environ['PATH_INFO'] = self._get_by_id(environ['PATH_INFO'])
234 repo_name = GIT_PROTO_PAT.match(environ['PATH_INFO']).group(1)
234 repo_name = GIT_PROTO_PAT.match(environ['PATH_INFO']).group(1)
235 except:
235 except:
236 log.error(traceback.format_exc())
236 log.error(traceback.format_exc())
237 raise
237 raise
238
238
239 return repo_name
239 return repo_name
240
240
241 def __get_user(self, username):
241 def __get_user(self, username):
242 return User.get_by_username(username)
242 return User.get_by_username(username)
243
243
244 def __get_action(self, environ):
244 def __get_action(self, environ):
245 """
245 """
246 Maps git request commands into a pull or push command.
246 Maps git request commands into a pull or push command.
247
247
248 :param environ:
248 :param environ:
249 """
249 """
250 service = environ['QUERY_STRING'].split('=')
250 service = environ['QUERY_STRING'].split('=')
251
251
252 if len(service) > 1:
252 if len(service) > 1:
253 service_cmd = service[1]
253 service_cmd = service[1]
254 mapping = {
254 mapping = {
255 'git-receive-pack': 'push',
255 'git-receive-pack': 'push',
256 'git-upload-pack': 'pull',
256 'git-upload-pack': 'pull',
257 }
257 }
258 op = mapping[service_cmd]
258 op = mapping[service_cmd]
259 self._git_stored_op = op
259 self._git_stored_op = op
260 return op
260 return op
261 else:
261 else:
262 # try to fallback to stored variable as we don't know if the last
262 # try to fallback to stored variable as we don't know if the last
263 # operation is pull/push
263 # operation is pull/push
264 op = getattr(self, '_git_stored_op', 'pull')
264 op = getattr(self, '_git_stored_op', 'pull')
265 return op
265 return op
266
266
267 def _handle_githooks(self, action, baseui, environ):
267 def _handle_githooks(self, repo_name, action, baseui, environ):
268 from rhodecode.lib.hooks import log_pull_action, log_push_action
268 from rhodecode.lib.hooks import log_pull_action, log_push_action
269 service = environ['QUERY_STRING'].split('=')
269 service = environ['QUERY_STRING'].split('=')
270 if len(service) < 2:
270 if len(service) < 2:
271 return
271 return
272
272
273 from rhodecode.model.db import Repository
273 from rhodecode.model.db import Repository
274 _repo = Repository.get_by_repo_name(repo_name)
274 _repo = Repository.get_by_repo_name(repo_name)
275 _repo = _repo.scm_instance
275 _repo = _repo.scm_instance
276 _repo._repo.ui = baseui
276 _repo._repo.ui = baseui
277
277
278 push_hook = 'pretxnchangegroup.push_logger'
278 push_hook = 'pretxnchangegroup.push_logger'
279 pull_hook = 'preoutgoing.pull_logger'
279 pull_hook = 'preoutgoing.pull_logger'
280 _hooks = dict(baseui.configitems('hooks')) or {}
280 _hooks = dict(baseui.configitems('hooks')) or {}
281 if action == 'push' and _hooks.get(push_hook):
281 if action == 'push' and _hooks.get(push_hook):
282 log_push_action(ui=baseui, repo=repo._repo)
282 log_push_action(ui=baseui, repo=_repo._repo)
283 elif action == 'pull' and _hooks.get(pull_hook):
283 elif action == 'pull' and _hooks.get(pull_hook):
284 log_pull_action(ui=baseui, repo=repo._repo)
284 log_pull_action(ui=baseui, repo=_repo._repo)
285
285
286 def __inject_extras(self, repo_path, baseui, extras={}):
286 def __inject_extras(self, repo_path, baseui, extras={}):
287 """
287 """
288 Injects some extra params into baseui instance
288 Injects some extra params into baseui instance
289
289
290 :param baseui: baseui instance
290 :param baseui: baseui instance
291 :param extras: dict with extra params to put into baseui
291 :param extras: dict with extra params to put into baseui
292 """
292 """
293
293
294 # make our hgweb quiet so it doesn't print output
294 # make our hgweb quiet so it doesn't print output
295 baseui.setconfig('ui', 'quiet', 'true')
295 baseui.setconfig('ui', 'quiet', 'true')
296
296
297 #inject some additional parameters that will be available in ui
297 #inject some additional parameters that will be available in ui
298 #for hooks
298 #for hooks
299 for k, v in extras.items():
299 for k, v in extras.items():
300 baseui.setconfig('rhodecode_extras', k, v)
300 baseui.setconfig('rhodecode_extras', k, v)
General Comments 0
You need to be logged in to leave comments. Login now