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