##// END OF EJS Templates
git: fixed code after version upgrade
marcink -
r434:74d2792f default
parent child Browse files
Show More
@@ -1,542 +1,543 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # RhodeCode VCSServer provides access to different vcs backends via network.
3 # RhodeCode VCSServer provides access to different vcs backends via network.
4 # Copyright (C) 2014-2018 RhodeCode GmbH
4 # Copyright (C) 2014-2018 RhodeCode GmbH
5 #
5 #
6 # This program is free software; you can redistribute it and/or modify
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
9 # (at your option) any later version.
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 Foundation,
17 # along with this program; if not, write to the Free Software Foundation,
18 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
19
20 import io
20 import io
21 import os
21 import os
22 import sys
22 import sys
23 import logging
23 import logging
24 import collections
24 import collections
25 import importlib
25 import importlib
26 import base64
26 import base64
27
27
28 from httplib import HTTPConnection
28 from httplib import HTTPConnection
29
29
30
30
31 import mercurial.scmutil
31 import mercurial.scmutil
32 import mercurial.node
32 import mercurial.node
33 import simplejson as json
33 import simplejson as json
34
34
35 from vcsserver import exceptions, subprocessio, settings
35 from vcsserver import exceptions, subprocessio, settings
36
36
37 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
38
38
39
39
40 class HooksHttpClient(object):
40 class HooksHttpClient(object):
41 connection = None
41 connection = None
42
42
43 def __init__(self, hooks_uri):
43 def __init__(self, hooks_uri):
44 self.hooks_uri = hooks_uri
44 self.hooks_uri = hooks_uri
45
45
46 def __call__(self, method, extras):
46 def __call__(self, method, extras):
47 connection = HTTPConnection(self.hooks_uri)
47 connection = HTTPConnection(self.hooks_uri)
48 body = self._serialize(method, extras)
48 body = self._serialize(method, extras)
49 try:
49 try:
50 connection.request('POST', '/', body)
50 connection.request('POST', '/', body)
51 except Exception:
51 except Exception:
52 log.error('Connection failed on %s', connection)
52 log.error('Connection failed on %s', connection)
53 raise
53 raise
54 response = connection.getresponse()
54 response = connection.getresponse()
55 return json.loads(response.read())
55 return json.loads(response.read())
56
56
57 def _serialize(self, hook_name, extras):
57 def _serialize(self, hook_name, extras):
58 data = {
58 data = {
59 'method': hook_name,
59 'method': hook_name,
60 'extras': extras
60 'extras': extras
61 }
61 }
62 return json.dumps(data)
62 return json.dumps(data)
63
63
64
64
65 class HooksDummyClient(object):
65 class HooksDummyClient(object):
66 def __init__(self, hooks_module):
66 def __init__(self, hooks_module):
67 self._hooks_module = importlib.import_module(hooks_module)
67 self._hooks_module = importlib.import_module(hooks_module)
68
68
69 def __call__(self, hook_name, extras):
69 def __call__(self, hook_name, extras):
70 with self._hooks_module.Hooks() as hooks:
70 with self._hooks_module.Hooks() as hooks:
71 return getattr(hooks, hook_name)(extras)
71 return getattr(hooks, hook_name)(extras)
72
72
73
73
74 class RemoteMessageWriter(object):
74 class RemoteMessageWriter(object):
75 """Writer base class."""
75 """Writer base class."""
76 def write(self, message):
76 def write(self, message):
77 raise NotImplementedError()
77 raise NotImplementedError()
78
78
79
79
80 class HgMessageWriter(RemoteMessageWriter):
80 class HgMessageWriter(RemoteMessageWriter):
81 """Writer that knows how to send messages to mercurial clients."""
81 """Writer that knows how to send messages to mercurial clients."""
82
82
83 def __init__(self, ui):
83 def __init__(self, ui):
84 self.ui = ui
84 self.ui = ui
85
85
86 def write(self, message):
86 def write(self, message):
87 # TODO: Check why the quiet flag is set by default.
87 # TODO: Check why the quiet flag is set by default.
88 old = self.ui.quiet
88 old = self.ui.quiet
89 self.ui.quiet = False
89 self.ui.quiet = False
90 self.ui.status(message.encode('utf-8'))
90 self.ui.status(message.encode('utf-8'))
91 self.ui.quiet = old
91 self.ui.quiet = old
92
92
93
93
94 class GitMessageWriter(RemoteMessageWriter):
94 class GitMessageWriter(RemoteMessageWriter):
95 """Writer that knows how to send messages to git clients."""
95 """Writer that knows how to send messages to git clients."""
96
96
97 def __init__(self, stdout=None):
97 def __init__(self, stdout=None):
98 self.stdout = stdout or sys.stdout
98 self.stdout = stdout or sys.stdout
99
99
100 def write(self, message):
100 def write(self, message):
101 self.stdout.write(message.encode('utf-8'))
101 self.stdout.write(message.encode('utf-8'))
102
102
103
103
104 class SvnMessageWriter(RemoteMessageWriter):
104 class SvnMessageWriter(RemoteMessageWriter):
105 """Writer that knows how to send messages to svn clients."""
105 """Writer that knows how to send messages to svn clients."""
106
106
107 def __init__(self, stderr=None):
107 def __init__(self, stderr=None):
108 # SVN needs data sent to stderr for back-to-client messaging
108 # SVN needs data sent to stderr for back-to-client messaging
109 self.stderr = stderr or sys.stderr
109 self.stderr = stderr or sys.stderr
110
110
111 def write(self, message):
111 def write(self, message):
112 self.stderr.write(message.encode('utf-8'))
112 self.stderr.write(message.encode('utf-8'))
113
113
114
114
115 def _handle_exception(result):
115 def _handle_exception(result):
116 exception_class = result.get('exception')
116 exception_class = result.get('exception')
117 exception_traceback = result.get('exception_traceback')
117 exception_traceback = result.get('exception_traceback')
118
118
119 if exception_traceback:
119 if exception_traceback:
120 log.error('Got traceback from remote call:%s', exception_traceback)
120 log.error('Got traceback from remote call:%s', exception_traceback)
121
121
122 if exception_class == 'HTTPLockedRC':
122 if exception_class == 'HTTPLockedRC':
123 raise exceptions.RepositoryLockedException(*result['exception_args'])
123 raise exceptions.RepositoryLockedException(*result['exception_args'])
124 elif exception_class == 'RepositoryError':
124 elif exception_class == 'RepositoryError':
125 raise exceptions.VcsException(*result['exception_args'])
125 raise exceptions.VcsException(*result['exception_args'])
126 elif exception_class:
126 elif exception_class:
127 raise Exception('Got remote exception "%s" with args "%s"' %
127 raise Exception('Got remote exception "%s" with args "%s"' %
128 (exception_class, result['exception_args']))
128 (exception_class, result['exception_args']))
129
129
130
130
131 def _get_hooks_client(extras):
131 def _get_hooks_client(extras):
132 if 'hooks_uri' in extras:
132 if 'hooks_uri' in extras:
133 protocol = extras.get('hooks_protocol')
133 protocol = extras.get('hooks_protocol')
134 return HooksHttpClient(extras['hooks_uri'])
134 return HooksHttpClient(extras['hooks_uri'])
135 else:
135 else:
136 return HooksDummyClient(extras['hooks_module'])
136 return HooksDummyClient(extras['hooks_module'])
137
137
138
138
139 def _call_hook(hook_name, extras, writer):
139 def _call_hook(hook_name, extras, writer):
140 hooks_client = _get_hooks_client(extras)
140 hooks_client = _get_hooks_client(extras)
141 log.debug('Hooks, using client:%s', hooks_client)
141 log.debug('Hooks, using client:%s', hooks_client)
142 result = hooks_client(hook_name, extras)
142 result = hooks_client(hook_name, extras)
143 log.debug('Hooks got result: %s', result)
143 log.debug('Hooks got result: %s', result)
144 writer.write(result['output'])
144 writer.write(result['output'])
145 _handle_exception(result)
145 _handle_exception(result)
146
146
147 return result['status']
147 return result['status']
148
148
149
149
150 def _extras_from_ui(ui):
150 def _extras_from_ui(ui):
151 hook_data = ui.config('rhodecode', 'RC_SCM_DATA')
151 hook_data = ui.config('rhodecode', 'RC_SCM_DATA')
152 if not hook_data:
152 if not hook_data:
153 # maybe it's inside environ ?
153 # maybe it's inside environ ?
154 env_hook_data = os.environ.get('RC_SCM_DATA')
154 env_hook_data = os.environ.get('RC_SCM_DATA')
155 if env_hook_data:
155 if env_hook_data:
156 hook_data = env_hook_data
156 hook_data = env_hook_data
157
157
158 extras = {}
158 extras = {}
159 if hook_data:
159 if hook_data:
160 extras = json.loads(hook_data)
160 extras = json.loads(hook_data)
161 return extras
161 return extras
162
162
163
163
164 def _rev_range_hash(repo, node):
164 def _rev_range_hash(repo, node):
165
165
166 commits = []
166 commits = []
167 start = repo[node].rev()
167 start = repo[node].rev()
168 for rev in xrange(start, len(repo)):
168 for rev in xrange(start, len(repo)):
169 ctx = repo[rev]
169 ctx = repo[rev]
170 commit_id = mercurial.node.hex(ctx.node())
170 commit_id = mercurial.node.hex(ctx.node())
171 branch = ctx.branch()
171 branch = ctx.branch()
172 commits.append((commit_id, branch))
172 commits.append((commit_id, branch))
173
173
174 return commits
174 return commits
175
175
176
176
177 def repo_size(ui, repo, **kwargs):
177 def repo_size(ui, repo, **kwargs):
178 extras = _extras_from_ui(ui)
178 extras = _extras_from_ui(ui)
179 return _call_hook('repo_size', extras, HgMessageWriter(ui))
179 return _call_hook('repo_size', extras, HgMessageWriter(ui))
180
180
181
181
182 def pre_pull(ui, repo, **kwargs):
182 def pre_pull(ui, repo, **kwargs):
183 extras = _extras_from_ui(ui)
183 extras = _extras_from_ui(ui)
184 return _call_hook('pre_pull', extras, HgMessageWriter(ui))
184 return _call_hook('pre_pull', extras, HgMessageWriter(ui))
185
185
186
186
187 def pre_pull_ssh(ui, repo, **kwargs):
187 def pre_pull_ssh(ui, repo, **kwargs):
188 extras = _extras_from_ui(ui)
188 extras = _extras_from_ui(ui)
189 if extras and extras.get('SSH'):
189 if extras and extras.get('SSH'):
190 return pre_pull(ui, repo, **kwargs)
190 return pre_pull(ui, repo, **kwargs)
191 return 0
191 return 0
192
192
193
193
194 def post_pull(ui, repo, **kwargs):
194 def post_pull(ui, repo, **kwargs):
195 extras = _extras_from_ui(ui)
195 extras = _extras_from_ui(ui)
196 return _call_hook('post_pull', extras, HgMessageWriter(ui))
196 return _call_hook('post_pull', extras, HgMessageWriter(ui))
197
197
198
198
199 def post_pull_ssh(ui, repo, **kwargs):
199 def post_pull_ssh(ui, repo, **kwargs):
200 extras = _extras_from_ui(ui)
200 extras = _extras_from_ui(ui)
201 if extras and extras.get('SSH'):
201 if extras and extras.get('SSH'):
202 return post_pull(ui, repo, **kwargs)
202 return post_pull(ui, repo, **kwargs)
203 return 0
203 return 0
204
204
205
205
206 def pre_push(ui, repo, node=None, **kwargs):
206 def pre_push(ui, repo, node=None, **kwargs):
207 extras = _extras_from_ui(ui)
207 extras = _extras_from_ui(ui)
208
208
209 rev_data = []
209 rev_data = []
210 if node and kwargs.get('hooktype') == 'pretxnchangegroup':
210 if node and kwargs.get('hooktype') == 'pretxnchangegroup':
211 branches = collections.defaultdict(list)
211 branches = collections.defaultdict(list)
212 for commit_id, branch in _rev_range_hash(repo, node):
212 for commit_id, branch in _rev_range_hash(repo, node):
213 branches[branch].append(commit_id)
213 branches[branch].append(commit_id)
214
214
215 for branch, commits in branches.iteritems():
215 for branch, commits in branches.iteritems():
216 old_rev = kwargs.get('node_last') or commits[0]
216 old_rev = kwargs.get('node_last') or commits[0]
217 rev_data.append({
217 rev_data.append({
218 'old_rev': old_rev,
218 'old_rev': old_rev,
219 'new_rev': commits[-1],
219 'new_rev': commits[-1],
220 'ref': '',
220 'ref': '',
221 'type': 'branch',
221 'type': 'branch',
222 'name': branch,
222 'name': branch,
223 })
223 })
224
224
225 extras['commit_ids'] = rev_data
225 extras['commit_ids'] = rev_data
226 return _call_hook('pre_push', extras, HgMessageWriter(ui))
226 return _call_hook('pre_push', extras, HgMessageWriter(ui))
227
227
228
228
229 def pre_push_ssh(ui, repo, node=None, **kwargs):
229 def pre_push_ssh(ui, repo, node=None, **kwargs):
230 if _extras_from_ui(ui).get('SSH'):
230 if _extras_from_ui(ui).get('SSH'):
231 return pre_push(ui, repo, node, **kwargs)
231 return pre_push(ui, repo, node, **kwargs)
232
232
233 return 0
233 return 0
234
234
235
235
236 def pre_push_ssh_auth(ui, repo, node=None, **kwargs):
236 def pre_push_ssh_auth(ui, repo, node=None, **kwargs):
237 extras = _extras_from_ui(ui)
237 extras = _extras_from_ui(ui)
238 if extras.get('SSH'):
238 if extras.get('SSH'):
239 permission = extras['SSH_PERMISSIONS']
239 permission = extras['SSH_PERMISSIONS']
240
240
241 if 'repository.write' == permission or 'repository.admin' == permission:
241 if 'repository.write' == permission or 'repository.admin' == permission:
242 return 0
242 return 0
243
243
244 # non-zero ret code
244 # non-zero ret code
245 return 1
245 return 1
246
246
247 return 0
247 return 0
248
248
249
249
250 def post_push(ui, repo, node, **kwargs):
250 def post_push(ui, repo, node, **kwargs):
251 extras = _extras_from_ui(ui)
251 extras = _extras_from_ui(ui)
252
252
253 commit_ids = []
253 commit_ids = []
254 branches = []
254 branches = []
255 bookmarks = []
255 bookmarks = []
256 tags = []
256 tags = []
257
257
258 for commit_id, branch in _rev_range_hash(repo, node):
258 for commit_id, branch in _rev_range_hash(repo, node):
259 commit_ids.append(commit_id)
259 commit_ids.append(commit_id)
260 if branch not in branches:
260 if branch not in branches:
261 branches.append(branch)
261 branches.append(branch)
262
262
263 if hasattr(ui, '_rc_pushkey_branches'):
263 if hasattr(ui, '_rc_pushkey_branches'):
264 bookmarks = ui._rc_pushkey_branches
264 bookmarks = ui._rc_pushkey_branches
265
265
266 extras['commit_ids'] = commit_ids
266 extras['commit_ids'] = commit_ids
267 extras['new_refs'] = {
267 extras['new_refs'] = {
268 'branches': branches,
268 'branches': branches,
269 'bookmarks': bookmarks,
269 'bookmarks': bookmarks,
270 'tags': tags
270 'tags': tags
271 }
271 }
272
272
273 return _call_hook('post_push', extras, HgMessageWriter(ui))
273 return _call_hook('post_push', extras, HgMessageWriter(ui))
274
274
275
275
276 def post_push_ssh(ui, repo, node, **kwargs):
276 def post_push_ssh(ui, repo, node, **kwargs):
277 if _extras_from_ui(ui).get('SSH'):
277 if _extras_from_ui(ui).get('SSH'):
278 return post_push(ui, repo, node, **kwargs)
278 return post_push(ui, repo, node, **kwargs)
279 return 0
279 return 0
280
280
281
281
282 def key_push(ui, repo, **kwargs):
282 def key_push(ui, repo, **kwargs):
283 if kwargs['new'] != '0' and kwargs['namespace'] == 'bookmarks':
283 if kwargs['new'] != '0' and kwargs['namespace'] == 'bookmarks':
284 # store new bookmarks in our UI object propagated later to post_push
284 # store new bookmarks in our UI object propagated later to post_push
285 ui._rc_pushkey_branches = repo[kwargs['key']].bookmarks()
285 ui._rc_pushkey_branches = repo[kwargs['key']].bookmarks()
286 return
286 return
287
287
288
288
289 # backward compat
289 # backward compat
290 log_pull_action = post_pull
290 log_pull_action = post_pull
291
291
292 # backward compat
292 # backward compat
293 log_push_action = post_push
293 log_push_action = post_push
294
294
295
295
296 def handle_git_pre_receive(unused_repo_path, unused_revs, unused_env):
296 def handle_git_pre_receive(unused_repo_path, unused_revs, unused_env):
297 """
297 """
298 Old hook name: keep here for backward compatibility.
298 Old hook name: keep here for backward compatibility.
299
299
300 This is only required when the installed git hooks are not upgraded.
300 This is only required when the installed git hooks are not upgraded.
301 """
301 """
302 pass
302 pass
303
303
304
304
305 def handle_git_post_receive(unused_repo_path, unused_revs, unused_env):
305 def handle_git_post_receive(unused_repo_path, unused_revs, unused_env):
306 """
306 """
307 Old hook name: keep here for backward compatibility.
307 Old hook name: keep here for backward compatibility.
308
308
309 This is only required when the installed git hooks are not upgraded.
309 This is only required when the installed git hooks are not upgraded.
310 """
310 """
311 pass
311 pass
312
312
313
313
314 HookResponse = collections.namedtuple('HookResponse', ('status', 'output'))
314 HookResponse = collections.namedtuple('HookResponse', ('status', 'output'))
315
315
316
316
317 def git_pre_pull(extras):
317 def git_pre_pull(extras):
318 """
318 """
319 Pre pull hook.
319 Pre pull hook.
320
320
321 :param extras: dictionary containing the keys defined in simplevcs
321 :param extras: dictionary containing the keys defined in simplevcs
322 :type extras: dict
322 :type extras: dict
323
323
324 :return: status code of the hook. 0 for success.
324 :return: status code of the hook. 0 for success.
325 :rtype: int
325 :rtype: int
326 """
326 """
327 if 'pull' not in extras['hooks']:
327 if 'pull' not in extras['hooks']:
328 return HookResponse(0, '')
328 return HookResponse(0, '')
329
329
330 stdout = io.BytesIO()
330 stdout = io.BytesIO()
331 try:
331 try:
332 status = _call_hook('pre_pull', extras, GitMessageWriter(stdout))
332 status = _call_hook('pre_pull', extras, GitMessageWriter(stdout))
333 except Exception as error:
333 except Exception as error:
334 status = 128
334 status = 128
335 stdout.write('ERROR: %s\n' % str(error))
335 stdout.write('ERROR: %s\n' % str(error))
336
336
337 return HookResponse(status, stdout.getvalue())
337 return HookResponse(status, stdout.getvalue())
338
338
339
339
340 def git_post_pull(extras):
340 def git_post_pull(extras):
341 """
341 """
342 Post pull hook.
342 Post pull hook.
343
343
344 :param extras: dictionary containing the keys defined in simplevcs
344 :param extras: dictionary containing the keys defined in simplevcs
345 :type extras: dict
345 :type extras: dict
346
346
347 :return: status code of the hook. 0 for success.
347 :return: status code of the hook. 0 for success.
348 :rtype: int
348 :rtype: int
349 """
349 """
350 if 'pull' not in extras['hooks']:
350 if 'pull' not in extras['hooks']:
351 return HookResponse(0, '')
351 return HookResponse(0, '')
352
352
353 stdout = io.BytesIO()
353 stdout = io.BytesIO()
354 try:
354 try:
355 status = _call_hook('post_pull', extras, GitMessageWriter(stdout))
355 status = _call_hook('post_pull', extras, GitMessageWriter(stdout))
356 except Exception as error:
356 except Exception as error:
357 status = 128
357 status = 128
358 stdout.write('ERROR: %s\n' % error)
358 stdout.write('ERROR: %s\n' % error)
359
359
360 return HookResponse(status, stdout.getvalue())
360 return HookResponse(status, stdout.getvalue())
361
361
362
362
363 def _parse_git_ref_lines(revision_lines):
363 def _parse_git_ref_lines(revision_lines):
364 rev_data = []
364 rev_data = []
365 for revision_line in revision_lines or []:
365 for revision_line in revision_lines or []:
366 old_rev, new_rev, ref = revision_line.strip().split(' ')
366 old_rev, new_rev, ref = revision_line.strip().split(' ')
367 ref_data = ref.split('/', 2)
367 ref_data = ref.split('/', 2)
368 if ref_data[1] in ('tags', 'heads'):
368 if ref_data[1] in ('tags', 'heads'):
369 rev_data.append({
369 rev_data.append({
370 'old_rev': old_rev,
370 'old_rev': old_rev,
371 'new_rev': new_rev,
371 'new_rev': new_rev,
372 'ref': ref,
372 'ref': ref,
373 'type': ref_data[1],
373 'type': ref_data[1],
374 'name': ref_data[2],
374 'name': ref_data[2],
375 })
375 })
376 return rev_data
376 return rev_data
377
377
378
378
379 def git_pre_receive(unused_repo_path, revision_lines, env):
379 def git_pre_receive(unused_repo_path, revision_lines, env):
380 """
380 """
381 Pre push hook.
381 Pre push hook.
382
382
383 :param extras: dictionary containing the keys defined in simplevcs
383 :param extras: dictionary containing the keys defined in simplevcs
384 :type extras: dict
384 :type extras: dict
385
385
386 :return: status code of the hook. 0 for success.
386 :return: status code of the hook. 0 for success.
387 :rtype: int
387 :rtype: int
388 """
388 """
389 extras = json.loads(env['RC_SCM_DATA'])
389 extras = json.loads(env['RC_SCM_DATA'])
390 rev_data = _parse_git_ref_lines(revision_lines)
390 rev_data = _parse_git_ref_lines(revision_lines)
391 if 'push' not in extras['hooks']:
391 if 'push' not in extras['hooks']:
392 return 0
392 return 0
393 extras['commit_ids'] = rev_data
393 extras['commit_ids'] = rev_data
394 return _call_hook('pre_push', extras, GitMessageWriter())
394 return _call_hook('pre_push', extras, GitMessageWriter())
395
395
396
396
397 def git_post_receive(unused_repo_path, revision_lines, env):
397 def git_post_receive(unused_repo_path, revision_lines, env):
398 """
398 """
399 Post push hook.
399 Post push hook.
400
400
401 :param extras: dictionary containing the keys defined in simplevcs
401 :param extras: dictionary containing the keys defined in simplevcs
402 :type extras: dict
402 :type extras: dict
403
403
404 :return: status code of the hook. 0 for success.
404 :return: status code of the hook. 0 for success.
405 :rtype: int
405 :rtype: int
406 """
406 """
407 extras = json.loads(env['RC_SCM_DATA'])
407 extras = json.loads(env['RC_SCM_DATA'])
408 if 'push' not in extras['hooks']:
408 if 'push' not in extras['hooks']:
409 return 0
409 return 0
410
410
411 rev_data = _parse_git_ref_lines(revision_lines)
411 rev_data = _parse_git_ref_lines(revision_lines)
412
412
413 git_revs = []
413 git_revs = []
414
414
415 # N.B.(skreft): it is ok to just call git, as git before calling a
415 # N.B.(skreft): it is ok to just call git, as git before calling a
416 # subcommand sets the PATH environment variable so that it point to the
416 # subcommand sets the PATH environment variable so that it point to the
417 # correct version of the git executable.
417 # correct version of the git executable.
418 empty_commit_id = '0' * 40
418 empty_commit_id = '0' * 40
419 branches = []
419 branches = []
420 tags = []
420 tags = []
421 for push_ref in rev_data:
421 for push_ref in rev_data:
422 type_ = push_ref['type']
422 type_ = push_ref['type']
423
423
424 if type_ == 'heads':
424 if type_ == 'heads':
425 if push_ref['old_rev'] == empty_commit_id:
425 if push_ref['old_rev'] == empty_commit_id:
426 # starting new branch case
426 # starting new branch case
427 if push_ref['name'] not in branches:
427 if push_ref['name'] not in branches:
428 branches.append(push_ref['name'])
428 branches.append(push_ref['name'])
429
429
430 # Fix up head revision if needed
430 # Fix up head revision if needed
431 cmd = [settings.GIT_EXECUTABLE, 'show', 'HEAD']
431 cmd = [settings.GIT_EXECUTABLE, 'show', 'HEAD']
432 try:
432 try:
433 subprocessio.run_command(cmd, env=os.environ.copy())
433 subprocessio.run_command(cmd, env=os.environ.copy())
434 except Exception:
434 except Exception:
435 cmd = [settings.GIT_EXECUTABLE, 'symbolic-ref', 'HEAD',
435 cmd = [settings.GIT_EXECUTABLE, 'symbolic-ref', 'HEAD',
436 'refs/heads/%s' % push_ref['name']]
436 'refs/heads/%s' % push_ref['name']]
437 print("Setting default branch to %s" % push_ref['name'])
437 print("Setting default branch to %s" % push_ref['name'])
438 subprocessio.run_command(cmd, env=os.environ.copy())
438 subprocessio.run_command(cmd, env=os.environ.copy())
439
439
440 cmd = [settings.GIT_EXECUTABLE, 'for-each-ref',
440 cmd = [settings.GIT_EXECUTABLE, 'for-each-ref',
441 '--format=%(refname)', 'refs/heads/*']
441 '--format=%(refname)', 'refs/heads/*']
442 stdout, stderr = subprocessio.run_command(
442 stdout, stderr = subprocessio.run_command(
443 cmd, env=os.environ.copy())
443 cmd, env=os.environ.copy())
444 heads = stdout
444 heads = stdout
445 heads = heads.replace(push_ref['ref'], '')
445 heads = heads.replace(push_ref['ref'], '')
446 heads = ' '.join(head for head in heads.splitlines() if head)
446 heads = ' '.join(head for head
447 in heads.splitlines() if head) or '.'
447 cmd = [settings.GIT_EXECUTABLE, 'log', '--reverse',
448 cmd = [settings.GIT_EXECUTABLE, 'log', '--reverse',
448 '--pretty=format:%H', '--', push_ref['new_rev'],
449 '--pretty=format:%H', '--', push_ref['new_rev'],
449 '--not', heads]
450 '--not', heads]
450 stdout, stderr = subprocessio.run_command(
451 stdout, stderr = subprocessio.run_command(
451 cmd, env=os.environ.copy())
452 cmd, env=os.environ.copy())
452 git_revs.extend(stdout.splitlines())
453 git_revs.extend(stdout.splitlines())
453 elif push_ref['new_rev'] == empty_commit_id:
454 elif push_ref['new_rev'] == empty_commit_id:
454 # delete branch case
455 # delete branch case
455 git_revs.append('delete_branch=>%s' % push_ref['name'])
456 git_revs.append('delete_branch=>%s' % push_ref['name'])
456 else:
457 else:
457 if push_ref['name'] not in branches:
458 if push_ref['name'] not in branches:
458 branches.append(push_ref['name'])
459 branches.append(push_ref['name'])
459
460
460 cmd = [settings.GIT_EXECUTABLE, 'log',
461 cmd = [settings.GIT_EXECUTABLE, 'log',
461 '{old_rev}..{new_rev}'.format(**push_ref),
462 '{old_rev}..{new_rev}'.format(**push_ref),
462 '--reverse', '--pretty=format:%H']
463 '--reverse', '--pretty=format:%H']
463 stdout, stderr = subprocessio.run_command(
464 stdout, stderr = subprocessio.run_command(
464 cmd, env=os.environ.copy())
465 cmd, env=os.environ.copy())
465 git_revs.extend(stdout.splitlines())
466 git_revs.extend(stdout.splitlines())
466 elif type_ == 'tags':
467 elif type_ == 'tags':
467 if push_ref['name'] not in tags:
468 if push_ref['name'] not in tags:
468 tags.append(push_ref['name'])
469 tags.append(push_ref['name'])
469 git_revs.append('tag=>%s' % push_ref['name'])
470 git_revs.append('tag=>%s' % push_ref['name'])
470
471
471 extras['commit_ids'] = git_revs
472 extras['commit_ids'] = git_revs
472 extras['new_refs'] = {
473 extras['new_refs'] = {
473 'branches': branches,
474 'branches': branches,
474 'bookmarks': [],
475 'bookmarks': [],
475 'tags': tags,
476 'tags': tags,
476 }
477 }
477
478
478 if 'repo_size' in extras['hooks']:
479 if 'repo_size' in extras['hooks']:
479 try:
480 try:
480 _call_hook('repo_size', extras, GitMessageWriter())
481 _call_hook('repo_size', extras, GitMessageWriter())
481 except:
482 except:
482 pass
483 pass
483
484
484 return _call_hook('post_push', extras, GitMessageWriter())
485 return _call_hook('post_push', extras, GitMessageWriter())
485
486
486
487
487 def svn_pre_commit(repo_path, commit_data, env):
488 def svn_pre_commit(repo_path, commit_data, env):
488 path, txn_id = commit_data
489 path, txn_id = commit_data
489 branches = []
490 branches = []
490 tags = []
491 tags = []
491
492
492 cmd = ['svnlook', 'pget',
493 cmd = ['svnlook', 'pget',
493 '-t', txn_id,
494 '-t', txn_id,
494 '--revprop', path, 'rc-scm-extras']
495 '--revprop', path, 'rc-scm-extras']
495 stdout, stderr = subprocessio.run_command(
496 stdout, stderr = subprocessio.run_command(
496 cmd, env=os.environ.copy())
497 cmd, env=os.environ.copy())
497 extras = json.loads(base64.urlsafe_b64decode(stdout))
498 extras = json.loads(base64.urlsafe_b64decode(stdout))
498
499
499 extras['commit_ids'] = []
500 extras['commit_ids'] = []
500 extras['txn_id'] = txn_id
501 extras['txn_id'] = txn_id
501 extras['new_refs'] = {
502 extras['new_refs'] = {
502 'branches': branches,
503 'branches': branches,
503 'bookmarks': [],
504 'bookmarks': [],
504 'tags': tags,
505 'tags': tags,
505 }
506 }
506 sys.stderr.write(str(extras))
507 sys.stderr.write(str(extras))
507 return _call_hook('pre_push', extras, SvnMessageWriter())
508 return _call_hook('pre_push', extras, SvnMessageWriter())
508
509
509
510
510 def svn_post_commit(repo_path, commit_data, env):
511 def svn_post_commit(repo_path, commit_data, env):
511 """
512 """
512 commit_data is path, rev, txn_id
513 commit_data is path, rev, txn_id
513 """
514 """
514 path, commit_id, txn_id = commit_data
515 path, commit_id, txn_id = commit_data
515 branches = []
516 branches = []
516 tags = []
517 tags = []
517
518
518 cmd = ['svnlook', 'pget',
519 cmd = ['svnlook', 'pget',
519 '-r', commit_id,
520 '-r', commit_id,
520 '--revprop', path, 'rc-scm-extras']
521 '--revprop', path, 'rc-scm-extras']
521 stdout, stderr = subprocessio.run_command(
522 stdout, stderr = subprocessio.run_command(
522 cmd, env=os.environ.copy())
523 cmd, env=os.environ.copy())
523
524
524 extras = json.loads(base64.urlsafe_b64decode(stdout))
525 extras = json.loads(base64.urlsafe_b64decode(stdout))
525
526
526 extras['commit_ids'] = [commit_id]
527 extras['commit_ids'] = [commit_id]
527 extras['txn_id'] = txn_id
528 extras['txn_id'] = txn_id
528 extras['new_refs'] = {
529 extras['new_refs'] = {
529 'branches': branches,
530 'branches': branches,
530 'bookmarks': [],
531 'bookmarks': [],
531 'tags': tags,
532 'tags': tags,
532 }
533 }
533
534
534 if 'repo_size' in extras['hooks']:
535 if 'repo_size' in extras['hooks']:
535 try:
536 try:
536 _call_hook('repo_size', extras, SvnMessageWriter())
537 _call_hook('repo_size', extras, SvnMessageWriter())
537 except:
538 except:
538 pass
539 pass
539
540
540 return _call_hook('post_push', extras, SvnMessageWriter())
541 return _call_hook('post_push', extras, SvnMessageWriter())
541
542
542
543
General Comments 0
You need to be logged in to leave comments. Login now