##// END OF EJS Templates
hooks: use safer method of exporting the RC_SCM_DATA, prevents JSON decode errors in case of None value
marcink -
r345:a3726eeb default
parent child Browse files
Show More
@@ -1,475 +1,478 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 hook_data = os.environ.get('RC_SCM_DATA')
139 env_hook_data = os.environ.get('RC_SCM_DATA')
140 if env_hook_data:
141 hook_data = env_hook_data
142
140 extras = json.loads(hook_data)
143 extras = json.loads(hook_data)
141 return extras
144 return extras
142
145
143
146
144 def _rev_range_hash(repo, node):
147 def _rev_range_hash(repo, node):
145
148
146 commits = []
149 commits = []
147 for rev in xrange(repo[node], len(repo)):
150 for rev in xrange(repo[node], len(repo)):
148 ctx = repo[rev]
151 ctx = repo[rev]
149 commit_id = mercurial.node.hex(ctx.node())
152 commit_id = mercurial.node.hex(ctx.node())
150 branch = ctx.branch()
153 branch = ctx.branch()
151 commits.append((commit_id, branch))
154 commits.append((commit_id, branch))
152
155
153 return commits
156 return commits
154
157
155
158
156 def repo_size(ui, repo, **kwargs):
159 def repo_size(ui, repo, **kwargs):
157 extras = _extras_from_ui(ui)
160 extras = _extras_from_ui(ui)
158 return _call_hook('repo_size', extras, HgMessageWriter(ui))
161 return _call_hook('repo_size', extras, HgMessageWriter(ui))
159
162
160
163
161 def pre_pull(ui, repo, **kwargs):
164 def pre_pull(ui, repo, **kwargs):
162 extras = _extras_from_ui(ui)
165 extras = _extras_from_ui(ui)
163 return _call_hook('pre_pull', extras, HgMessageWriter(ui))
166 return _call_hook('pre_pull', extras, HgMessageWriter(ui))
164
167
165
168
166 def pre_pull_ssh(ui, repo, **kwargs):
169 def pre_pull_ssh(ui, repo, **kwargs):
167 if _extras_from_ui(ui).get('SSH'):
170 if _extras_from_ui(ui).get('SSH'):
168 return pre_pull(ui, repo, **kwargs)
171 return pre_pull(ui, repo, **kwargs)
169 return 0
172 return 0
170
173
171
174
172 def post_pull(ui, repo, **kwargs):
175 def post_pull(ui, repo, **kwargs):
173 extras = _extras_from_ui(ui)
176 extras = _extras_from_ui(ui)
174 return _call_hook('post_pull', extras, HgMessageWriter(ui))
177 return _call_hook('post_pull', extras, HgMessageWriter(ui))
175
178
176
179
177 def post_pull_ssh(ui, repo, **kwargs):
180 def post_pull_ssh(ui, repo, **kwargs):
178 if _extras_from_ui(ui).get('SSH'):
181 if _extras_from_ui(ui).get('SSH'):
179 return post_pull(ui, repo, **kwargs)
182 return post_pull(ui, repo, **kwargs)
180 return 0
183 return 0
181
184
182
185
183 def pre_push(ui, repo, node=None, **kwargs):
186 def pre_push(ui, repo, node=None, **kwargs):
184 extras = _extras_from_ui(ui)
187 extras = _extras_from_ui(ui)
185
188
186 rev_data = []
189 rev_data = []
187 if node and kwargs.get('hooktype') == 'pretxnchangegroup':
190 if node and kwargs.get('hooktype') == 'pretxnchangegroup':
188 branches = collections.defaultdict(list)
191 branches = collections.defaultdict(list)
189 for commit_id, branch in _rev_range_hash(repo, node):
192 for commit_id, branch in _rev_range_hash(repo, node):
190 branches[branch].append(commit_id)
193 branches[branch].append(commit_id)
191
194
192 for branch, commits in branches.iteritems():
195 for branch, commits in branches.iteritems():
193 old_rev = kwargs.get('node_last') or commits[0]
196 old_rev = kwargs.get('node_last') or commits[0]
194 rev_data.append({
197 rev_data.append({
195 'old_rev': old_rev,
198 'old_rev': old_rev,
196 'new_rev': commits[-1],
199 'new_rev': commits[-1],
197 'ref': '',
200 'ref': '',
198 'type': 'branch',
201 'type': 'branch',
199 'name': branch,
202 'name': branch,
200 })
203 })
201
204
202 extras['commit_ids'] = rev_data
205 extras['commit_ids'] = rev_data
203 return _call_hook('pre_push', extras, HgMessageWriter(ui))
206 return _call_hook('pre_push', extras, HgMessageWriter(ui))
204
207
205
208
206 def pre_push_ssh(ui, repo, node=None, **kwargs):
209 def pre_push_ssh(ui, repo, node=None, **kwargs):
207 if _extras_from_ui(ui).get('SSH'):
210 if _extras_from_ui(ui).get('SSH'):
208 return pre_push(ui, repo, node, **kwargs)
211 return pre_push(ui, repo, node, **kwargs)
209
212
210 return 0
213 return 0
211
214
212
215
213 def pre_push_ssh_auth(ui, repo, node=None, **kwargs):
216 def pre_push_ssh_auth(ui, repo, node=None, **kwargs):
214 extras = _extras_from_ui(ui)
217 extras = _extras_from_ui(ui)
215 if extras.get('SSH'):
218 if extras.get('SSH'):
216 permission = extras['SSH_PERMISSIONS']
219 permission = extras['SSH_PERMISSIONS']
217
220
218 if 'repository.write' == permission or 'repository.admin' == permission:
221 if 'repository.write' == permission or 'repository.admin' == permission:
219 return 0
222 return 0
220
223
221 # non-zero ret code
224 # non-zero ret code
222 return 1
225 return 1
223
226
224 return 0
227 return 0
225
228
226
229
227 def post_push(ui, repo, node, **kwargs):
230 def post_push(ui, repo, node, **kwargs):
228 extras = _extras_from_ui(ui)
231 extras = _extras_from_ui(ui)
229
232
230 commit_ids = []
233 commit_ids = []
231 branches = []
234 branches = []
232 bookmarks = []
235 bookmarks = []
233 tags = []
236 tags = []
234
237
235 for commit_id, branch in _rev_range_hash(repo, node):
238 for commit_id, branch in _rev_range_hash(repo, node):
236 commit_ids.append(commit_id)
239 commit_ids.append(commit_id)
237 if branch not in branches:
240 if branch not in branches:
238 branches.append(branch)
241 branches.append(branch)
239
242
240 if hasattr(ui, '_rc_pushkey_branches'):
243 if hasattr(ui, '_rc_pushkey_branches'):
241 bookmarks = ui._rc_pushkey_branches
244 bookmarks = ui._rc_pushkey_branches
242
245
243 extras['commit_ids'] = commit_ids
246 extras['commit_ids'] = commit_ids
244 extras['new_refs'] = {
247 extras['new_refs'] = {
245 'branches': branches,
248 'branches': branches,
246 'bookmarks': bookmarks,
249 'bookmarks': bookmarks,
247 'tags': tags
250 'tags': tags
248 }
251 }
249
252
250 return _call_hook('post_push', extras, HgMessageWriter(ui))
253 return _call_hook('post_push', extras, HgMessageWriter(ui))
251
254
252
255
253 def post_push_ssh(ui, repo, node, **kwargs):
256 def post_push_ssh(ui, repo, node, **kwargs):
254 if _extras_from_ui(ui).get('SSH'):
257 if _extras_from_ui(ui).get('SSH'):
255 return post_push(ui, repo, node, **kwargs)
258 return post_push(ui, repo, node, **kwargs)
256 return 0
259 return 0
257
260
258
261
259 def key_push(ui, repo, **kwargs):
262 def key_push(ui, repo, **kwargs):
260 if kwargs['new'] != '0' and kwargs['namespace'] == 'bookmarks':
263 if kwargs['new'] != '0' and kwargs['namespace'] == 'bookmarks':
261 # store new bookmarks in our UI object propagated later to post_push
264 # store new bookmarks in our UI object propagated later to post_push
262 ui._rc_pushkey_branches = repo[kwargs['key']].bookmarks()
265 ui._rc_pushkey_branches = repo[kwargs['key']].bookmarks()
263 return
266 return
264
267
265
268
266 # backward compat
269 # backward compat
267 log_pull_action = post_pull
270 log_pull_action = post_pull
268
271
269 # backward compat
272 # backward compat
270 log_push_action = post_push
273 log_push_action = post_push
271
274
272
275
273 def handle_git_pre_receive(unused_repo_path, unused_revs, unused_env):
276 def handle_git_pre_receive(unused_repo_path, unused_revs, unused_env):
274 """
277 """
275 Old hook name: keep here for backward compatibility.
278 Old hook name: keep here for backward compatibility.
276
279
277 This is only required when the installed git hooks are not upgraded.
280 This is only required when the installed git hooks are not upgraded.
278 """
281 """
279 pass
282 pass
280
283
281
284
282 def handle_git_post_receive(unused_repo_path, unused_revs, unused_env):
285 def handle_git_post_receive(unused_repo_path, unused_revs, unused_env):
283 """
286 """
284 Old hook name: keep here for backward compatibility.
287 Old hook name: keep here for backward compatibility.
285
288
286 This is only required when the installed git hooks are not upgraded.
289 This is only required when the installed git hooks are not upgraded.
287 """
290 """
288 pass
291 pass
289
292
290
293
291 HookResponse = collections.namedtuple('HookResponse', ('status', 'output'))
294 HookResponse = collections.namedtuple('HookResponse', ('status', 'output'))
292
295
293
296
294 def git_pre_pull(extras):
297 def git_pre_pull(extras):
295 """
298 """
296 Pre pull hook.
299 Pre pull hook.
297
300
298 :param extras: dictionary containing the keys defined in simplevcs
301 :param extras: dictionary containing the keys defined in simplevcs
299 :type extras: dict
302 :type extras: dict
300
303
301 :return: status code of the hook. 0 for success.
304 :return: status code of the hook. 0 for success.
302 :rtype: int
305 :rtype: int
303 """
306 """
304 if 'pull' not in extras['hooks']:
307 if 'pull' not in extras['hooks']:
305 return HookResponse(0, '')
308 return HookResponse(0, '')
306
309
307 stdout = io.BytesIO()
310 stdout = io.BytesIO()
308 try:
311 try:
309 status = _call_hook('pre_pull', extras, GitMessageWriter(stdout))
312 status = _call_hook('pre_pull', extras, GitMessageWriter(stdout))
310 except Exception as error:
313 except Exception as error:
311 status = 128
314 status = 128
312 stdout.write('ERROR: %s\n' % str(error))
315 stdout.write('ERROR: %s\n' % str(error))
313
316
314 return HookResponse(status, stdout.getvalue())
317 return HookResponse(status, stdout.getvalue())
315
318
316
319
317 def git_post_pull(extras):
320 def git_post_pull(extras):
318 """
321 """
319 Post pull hook.
322 Post pull hook.
320
323
321 :param extras: dictionary containing the keys defined in simplevcs
324 :param extras: dictionary containing the keys defined in simplevcs
322 :type extras: dict
325 :type extras: dict
323
326
324 :return: status code of the hook. 0 for success.
327 :return: status code of the hook. 0 for success.
325 :rtype: int
328 :rtype: int
326 """
329 """
327 if 'pull' not in extras['hooks']:
330 if 'pull' not in extras['hooks']:
328 return HookResponse(0, '')
331 return HookResponse(0, '')
329
332
330 stdout = io.BytesIO()
333 stdout = io.BytesIO()
331 try:
334 try:
332 status = _call_hook('post_pull', extras, GitMessageWriter(stdout))
335 status = _call_hook('post_pull', extras, GitMessageWriter(stdout))
333 except Exception as error:
336 except Exception as error:
334 status = 128
337 status = 128
335 stdout.write('ERROR: %s\n' % error)
338 stdout.write('ERROR: %s\n' % error)
336
339
337 return HookResponse(status, stdout.getvalue())
340 return HookResponse(status, stdout.getvalue())
338
341
339
342
340 def _parse_git_ref_lines(revision_lines):
343 def _parse_git_ref_lines(revision_lines):
341 rev_data = []
344 rev_data = []
342 for revision_line in revision_lines or []:
345 for revision_line in revision_lines or []:
343 old_rev, new_rev, ref = revision_line.strip().split(' ')
346 old_rev, new_rev, ref = revision_line.strip().split(' ')
344 ref_data = ref.split('/', 2)
347 ref_data = ref.split('/', 2)
345 if ref_data[1] in ('tags', 'heads'):
348 if ref_data[1] in ('tags', 'heads'):
346 rev_data.append({
349 rev_data.append({
347 'old_rev': old_rev,
350 'old_rev': old_rev,
348 'new_rev': new_rev,
351 'new_rev': new_rev,
349 'ref': ref,
352 'ref': ref,
350 'type': ref_data[1],
353 'type': ref_data[1],
351 'name': ref_data[2],
354 'name': ref_data[2],
352 })
355 })
353 return rev_data
356 return rev_data
354
357
355
358
356 def git_pre_receive(unused_repo_path, revision_lines, env):
359 def git_pre_receive(unused_repo_path, revision_lines, env):
357 """
360 """
358 Pre push hook.
361 Pre push hook.
359
362
360 :param extras: dictionary containing the keys defined in simplevcs
363 :param extras: dictionary containing the keys defined in simplevcs
361 :type extras: dict
364 :type extras: dict
362
365
363 :return: status code of the hook. 0 for success.
366 :return: status code of the hook. 0 for success.
364 :rtype: int
367 :rtype: int
365 """
368 """
366 extras = json.loads(env['RC_SCM_DATA'])
369 extras = json.loads(env['RC_SCM_DATA'])
367 rev_data = _parse_git_ref_lines(revision_lines)
370 rev_data = _parse_git_ref_lines(revision_lines)
368 if 'push' not in extras['hooks']:
371 if 'push' not in extras['hooks']:
369 return 0
372 return 0
370 extras['commit_ids'] = rev_data
373 extras['commit_ids'] = rev_data
371 return _call_hook('pre_push', extras, GitMessageWriter())
374 return _call_hook('pre_push', extras, GitMessageWriter())
372
375
373
376
374 def _run_command(arguments):
377 def _run_command(arguments):
375 """
378 """
376 Run the specified command and return the stdout.
379 Run the specified command and return the stdout.
377
380
378 :param arguments: sequence of program arguments (including the program name)
381 :param arguments: sequence of program arguments (including the program name)
379 :type arguments: list[str]
382 :type arguments: list[str]
380 """
383 """
381 # TODO(skreft): refactor this method and all the other similar ones.
384 # TODO(skreft): refactor this method and all the other similar ones.
382 # Probably this should be using subprocessio.
385 # Probably this should be using subprocessio.
383 process = subprocess.Popen(
386 process = subprocess.Popen(
384 arguments, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
387 arguments, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
385 stdout, stderr = process.communicate()
388 stdout, stderr = process.communicate()
386
389
387 if process.returncode != 0:
390 if process.returncode != 0:
388 raise Exception(
391 raise Exception(
389 'Command %s exited with exit code %s: stderr:%s' % (
392 'Command %s exited with exit code %s: stderr:%s' % (
390 arguments, process.returncode, stderr))
393 arguments, process.returncode, stderr))
391
394
392 return stdout
395 return stdout
393
396
394
397
395 def git_post_receive(unused_repo_path, revision_lines, env):
398 def git_post_receive(unused_repo_path, revision_lines, env):
396 """
399 """
397 Post push hook.
400 Post push hook.
398
401
399 :param extras: dictionary containing the keys defined in simplevcs
402 :param extras: dictionary containing the keys defined in simplevcs
400 :type extras: dict
403 :type extras: dict
401
404
402 :return: status code of the hook. 0 for success.
405 :return: status code of the hook. 0 for success.
403 :rtype: int
406 :rtype: int
404 """
407 """
405 extras = json.loads(env['RC_SCM_DATA'])
408 extras = json.loads(env['RC_SCM_DATA'])
406 if 'push' not in extras['hooks']:
409 if 'push' not in extras['hooks']:
407 return 0
410 return 0
408
411
409 rev_data = _parse_git_ref_lines(revision_lines)
412 rev_data = _parse_git_ref_lines(revision_lines)
410
413
411 git_revs = []
414 git_revs = []
412
415
413 # N.B.(skreft): it is ok to just call git, as git before calling a
416 # N.B.(skreft): it is ok to just call git, as git before calling a
414 # subcommand sets the PATH environment variable so that it point to the
417 # subcommand sets the PATH environment variable so that it point to the
415 # correct version of the git executable.
418 # correct version of the git executable.
416 empty_commit_id = '0' * 40
419 empty_commit_id = '0' * 40
417 branches = []
420 branches = []
418 tags = []
421 tags = []
419 for push_ref in rev_data:
422 for push_ref in rev_data:
420 type_ = push_ref['type']
423 type_ = push_ref['type']
421
424
422 if type_ == 'heads':
425 if type_ == 'heads':
423 if push_ref['old_rev'] == empty_commit_id:
426 if push_ref['old_rev'] == empty_commit_id:
424 # starting new branch case
427 # starting new branch case
425 if push_ref['name'] not in branches:
428 if push_ref['name'] not in branches:
426 branches.append(push_ref['name'])
429 branches.append(push_ref['name'])
427
430
428 # Fix up head revision if needed
431 # Fix up head revision if needed
429 cmd = ['git', 'show', 'HEAD']
432 cmd = ['git', 'show', 'HEAD']
430 try:
433 try:
431 _run_command(cmd)
434 _run_command(cmd)
432 except Exception:
435 except Exception:
433 cmd = ['git', 'symbolic-ref', 'HEAD',
436 cmd = ['git', 'symbolic-ref', 'HEAD',
434 'refs/heads/%s' % push_ref['name']]
437 'refs/heads/%s' % push_ref['name']]
435 print("Setting default branch to %s" % push_ref['name'])
438 print("Setting default branch to %s" % push_ref['name'])
436 _run_command(cmd)
439 _run_command(cmd)
437
440
438 cmd = ['git', 'for-each-ref', '--format=%(refname)',
441 cmd = ['git', 'for-each-ref', '--format=%(refname)',
439 'refs/heads/*']
442 'refs/heads/*']
440 heads = _run_command(cmd)
443 heads = _run_command(cmd)
441 heads = heads.replace(push_ref['ref'], '')
444 heads = heads.replace(push_ref['ref'], '')
442 heads = ' '.join(head for head in heads.splitlines() if head)
445 heads = ' '.join(head for head in heads.splitlines() if head)
443 cmd = ['git', 'log', '--reverse', '--pretty=format:%H',
446 cmd = ['git', 'log', '--reverse', '--pretty=format:%H',
444 '--', push_ref['new_rev'], '--not', heads]
447 '--', push_ref['new_rev'], '--not', heads]
445 git_revs.extend(_run_command(cmd).splitlines())
448 git_revs.extend(_run_command(cmd).splitlines())
446 elif push_ref['new_rev'] == empty_commit_id:
449 elif push_ref['new_rev'] == empty_commit_id:
447 # delete branch case
450 # delete branch case
448 git_revs.append('delete_branch=>%s' % push_ref['name'])
451 git_revs.append('delete_branch=>%s' % push_ref['name'])
449 else:
452 else:
450 if push_ref['name'] not in branches:
453 if push_ref['name'] not in branches:
451 branches.append(push_ref['name'])
454 branches.append(push_ref['name'])
452
455
453 cmd = ['git', 'log',
456 cmd = ['git', 'log',
454 '{old_rev}..{new_rev}'.format(**push_ref),
457 '{old_rev}..{new_rev}'.format(**push_ref),
455 '--reverse', '--pretty=format:%H']
458 '--reverse', '--pretty=format:%H']
456 git_revs.extend(_run_command(cmd).splitlines())
459 git_revs.extend(_run_command(cmd).splitlines())
457 elif type_ == 'tags':
460 elif type_ == 'tags':
458 if push_ref['name'] not in tags:
461 if push_ref['name'] not in tags:
459 tags.append(push_ref['name'])
462 tags.append(push_ref['name'])
460 git_revs.append('tag=>%s' % push_ref['name'])
463 git_revs.append('tag=>%s' % push_ref['name'])
461
464
462 extras['commit_ids'] = git_revs
465 extras['commit_ids'] = git_revs
463 extras['new_refs'] = {
466 extras['new_refs'] = {
464 'branches': branches,
467 'branches': branches,
465 'bookmarks': [],
468 'bookmarks': [],
466 'tags': tags,
469 'tags': tags,
467 }
470 }
468
471
469 if 'repo_size' in extras['hooks']:
472 if 'repo_size' in extras['hooks']:
470 try:
473 try:
471 _call_hook('repo_size', extras, GitMessageWriter())
474 _call_hook('repo_size', extras, GitMessageWriter())
472 except:
475 except:
473 pass
476 pass
474
477
475 return _call_hook('post_push', extras, GitMessageWriter())
478 return _call_hook('post_push', extras, GitMessageWriter())
General Comments 0
You need to be logged in to leave comments. Login now