##// END OF EJS Templates
hooks: added shadow repo dedicated dummy hook....
marcink -
r780:baf64deb default
parent child Browse files
Show More
@@ -1,711 +1,720 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # RhodeCode VCSServer provides access to different vcs backends via network.
4 4 # Copyright (C) 2014-2019 RhodeCode GmbH
5 5 #
6 6 # This program is free software; you can redistribute it and/or modify
7 7 # it under the terms of the GNU General Public License as published by
8 8 # the Free Software Foundation; either version 3 of the License, or
9 9 # (at your option) any later version.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software Foundation,
18 18 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 19
20 20 import io
21 21 import os
22 22 import sys
23 23 import logging
24 24 import collections
25 25 import importlib
26 26 import base64
27 27
28 28 from httplib import HTTPConnection
29 29
30 30
31 31 import mercurial.scmutil
32 32 import mercurial.node
33 33 import simplejson as json
34 34
35 35 from vcsserver import exceptions, subprocessio, settings
36 36 from vcsserver.hgcompat import get_ctx
37 37
38 38 log = logging.getLogger(__name__)
39 39
40 40
41 41 class HooksHttpClient(object):
42 42 connection = None
43 43
44 44 def __init__(self, hooks_uri):
45 45 self.hooks_uri = hooks_uri
46 46
47 47 def __call__(self, method, extras):
48 48 connection = HTTPConnection(self.hooks_uri)
49 49 body = self._serialize(method, extras)
50 50 try:
51 51 connection.request('POST', '/', body)
52 52 except Exception:
53 53 log.error('Connection failed on %s', connection)
54 54 raise
55 55 response = connection.getresponse()
56 56
57 57 response_data = response.read()
58 58
59 59 try:
60 60 return json.loads(response_data)
61 61 except Exception:
62 62 log.exception('Failed to decode hook response json data. '
63 63 'response_code:%s, raw_data:%s',
64 64 response.status, response_data)
65 65 raise
66 66
67 67 def _serialize(self, hook_name, extras):
68 68 data = {
69 69 'method': hook_name,
70 70 'extras': extras
71 71 }
72 72 return json.dumps(data)
73 73
74 74
75 75 class HooksDummyClient(object):
76 76 def __init__(self, hooks_module):
77 77 self._hooks_module = importlib.import_module(hooks_module)
78 78
79 79 def __call__(self, hook_name, extras):
80 80 with self._hooks_module.Hooks() as hooks:
81 81 return getattr(hooks, hook_name)(extras)
82 82
83 83
84 class HooksShadowRepoClient(object):
85
86 def __call__(self, hook_name, extras):
87 return {'output': '', 'status': 0}
88
89
84 90 class RemoteMessageWriter(object):
85 91 """Writer base class."""
86 92 def write(self, message):
87 93 raise NotImplementedError()
88 94
89 95
90 96 class HgMessageWriter(RemoteMessageWriter):
91 97 """Writer that knows how to send messages to mercurial clients."""
92 98
93 99 def __init__(self, ui):
94 100 self.ui = ui
95 101
96 102 def write(self, message):
97 103 # TODO: Check why the quiet flag is set by default.
98 104 old = self.ui.quiet
99 105 self.ui.quiet = False
100 106 self.ui.status(message.encode('utf-8'))
101 107 self.ui.quiet = old
102 108
103 109
104 110 class GitMessageWriter(RemoteMessageWriter):
105 111 """Writer that knows how to send messages to git clients."""
106 112
107 113 def __init__(self, stdout=None):
108 114 self.stdout = stdout or sys.stdout
109 115
110 116 def write(self, message):
111 117 self.stdout.write(message.encode('utf-8'))
112 118
113 119
114 120 class SvnMessageWriter(RemoteMessageWriter):
115 121 """Writer that knows how to send messages to svn clients."""
116 122
117 123 def __init__(self, stderr=None):
118 124 # SVN needs data sent to stderr for back-to-client messaging
119 125 self.stderr = stderr or sys.stderr
120 126
121 127 def write(self, message):
122 128 self.stderr.write(message.encode('utf-8'))
123 129
124 130
125 131 def _handle_exception(result):
126 132 exception_class = result.get('exception')
127 133 exception_traceback = result.get('exception_traceback')
128 134
129 135 if exception_traceback:
130 136 log.error('Got traceback from remote call:%s', exception_traceback)
131 137
132 138 if exception_class == 'HTTPLockedRC':
133 139 raise exceptions.RepositoryLockedException()(*result['exception_args'])
134 140 elif exception_class == 'HTTPBranchProtected':
135 141 raise exceptions.RepositoryBranchProtectedException()(*result['exception_args'])
136 142 elif exception_class == 'RepositoryError':
137 143 raise exceptions.VcsException()(*result['exception_args'])
138 144 elif exception_class:
139 145 raise Exception('Got remote exception "%s" with args "%s"' %
140 146 (exception_class, result['exception_args']))
141 147
142 148
143 149 def _get_hooks_client(extras):
144 if 'hooks_uri' in extras:
145 protocol = extras.get('hooks_protocol')
150 hooks_uri = extras.get('hooks_uri')
151 is_shadow_repo = extras.get('is_shadow_repo')
152 if hooks_uri:
146 153 return HooksHttpClient(extras['hooks_uri'])
154 elif is_shadow_repo:
155 return HooksShadowRepoClient()
147 156 else:
148 157 return HooksDummyClient(extras['hooks_module'])
149 158
150 159
151 160 def _call_hook(hook_name, extras, writer):
152 161 hooks_client = _get_hooks_client(extras)
153 162 log.debug('Hooks, using client:%s', hooks_client)
154 163 result = hooks_client(hook_name, extras)
155 164 log.debug('Hooks got result: %s', result)
156 165
157 166 _handle_exception(result)
158 167 writer.write(result['output'])
159 168
160 169 return result['status']
161 170
162 171
163 172 def _extras_from_ui(ui):
164 173 hook_data = ui.config('rhodecode', 'RC_SCM_DATA')
165 174 if not hook_data:
166 175 # maybe it's inside environ ?
167 176 env_hook_data = os.environ.get('RC_SCM_DATA')
168 177 if env_hook_data:
169 178 hook_data = env_hook_data
170 179
171 180 extras = {}
172 181 if hook_data:
173 182 extras = json.loads(hook_data)
174 183 return extras
175 184
176 185
177 186 def _rev_range_hash(repo, node, check_heads=False):
178 187
179 188 commits = []
180 189 revs = []
181 190 start = get_ctx(repo, node).rev()
182 191 end = len(repo)
183 192 for rev in range(start, end):
184 193 revs.append(rev)
185 194 ctx = get_ctx(repo, rev)
186 195 commit_id = mercurial.node.hex(ctx.node())
187 196 branch = ctx.branch()
188 197 commits.append((commit_id, branch))
189 198
190 199 parent_heads = []
191 200 if check_heads:
192 201 parent_heads = _check_heads(repo, start, end, revs)
193 202 return commits, parent_heads
194 203
195 204
196 205 def _check_heads(repo, start, end, commits):
197 206 changelog = repo.changelog
198 207 parents = set()
199 208
200 209 for new_rev in commits:
201 210 for p in changelog.parentrevs(new_rev):
202 211 if p == mercurial.node.nullrev:
203 212 continue
204 213 if p < start:
205 214 parents.add(p)
206 215
207 216 for p in parents:
208 217 branch = get_ctx(repo, p).branch()
209 218 # The heads descending from that parent, on the same branch
210 219 parent_heads = set([p])
211 220 reachable = set([p])
212 221 for x in xrange(p + 1, end):
213 222 if get_ctx(repo, x).branch() != branch:
214 223 continue
215 224 for pp in changelog.parentrevs(x):
216 225 if pp in reachable:
217 226 reachable.add(x)
218 227 parent_heads.discard(pp)
219 228 parent_heads.add(x)
220 229 # More than one head? Suggest merging
221 230 if len(parent_heads) > 1:
222 231 return list(parent_heads)
223 232
224 233 return []
225 234
226 235
227 236 def _get_git_env():
228 237 env = {}
229 238 for k, v in os.environ.items():
230 239 if k.startswith('GIT'):
231 240 env[k] = v
232 241
233 242 # serialized version
234 243 return [(k, v) for k, v in env.items()]
235 244
236 245
237 246 def _get_hg_env(old_rev, new_rev, txnid, repo_path):
238 247 env = {}
239 248 for k, v in os.environ.items():
240 249 if k.startswith('HG'):
241 250 env[k] = v
242 251
243 252 env['HG_NODE'] = old_rev
244 253 env['HG_NODE_LAST'] = new_rev
245 254 env['HG_TXNID'] = txnid
246 255 env['HG_PENDING'] = repo_path
247 256
248 257 return [(k, v) for k, v in env.items()]
249 258
250 259
251 260 def repo_size(ui, repo, **kwargs):
252 261 extras = _extras_from_ui(ui)
253 262 return _call_hook('repo_size', extras, HgMessageWriter(ui))
254 263
255 264
256 265 def pre_pull(ui, repo, **kwargs):
257 266 extras = _extras_from_ui(ui)
258 267 return _call_hook('pre_pull', extras, HgMessageWriter(ui))
259 268
260 269
261 270 def pre_pull_ssh(ui, repo, **kwargs):
262 271 extras = _extras_from_ui(ui)
263 272 if extras and extras.get('SSH'):
264 273 return pre_pull(ui, repo, **kwargs)
265 274 return 0
266 275
267 276
268 277 def post_pull(ui, repo, **kwargs):
269 278 extras = _extras_from_ui(ui)
270 279 return _call_hook('post_pull', extras, HgMessageWriter(ui))
271 280
272 281
273 282 def post_pull_ssh(ui, repo, **kwargs):
274 283 extras = _extras_from_ui(ui)
275 284 if extras and extras.get('SSH'):
276 285 return post_pull(ui, repo, **kwargs)
277 286 return 0
278 287
279 288
280 289 def pre_push(ui, repo, node=None, **kwargs):
281 290 """
282 291 Mercurial pre_push hook
283 292 """
284 293 extras = _extras_from_ui(ui)
285 294 detect_force_push = extras.get('detect_force_push')
286 295
287 296 rev_data = []
288 297 if node and kwargs.get('hooktype') == 'pretxnchangegroup':
289 298 branches = collections.defaultdict(list)
290 299 commits, _heads = _rev_range_hash(repo, node, check_heads=detect_force_push)
291 300 for commit_id, branch in commits:
292 301 branches[branch].append(commit_id)
293 302
294 303 for branch, commits in branches.items():
295 304 old_rev = kwargs.get('node_last') or commits[0]
296 305 rev_data.append({
297 306 'total_commits': len(commits),
298 307 'old_rev': old_rev,
299 308 'new_rev': commits[-1],
300 309 'ref': '',
301 310 'type': 'branch',
302 311 'name': branch,
303 312 })
304 313
305 314 for push_ref in rev_data:
306 315 push_ref['multiple_heads'] = _heads
307 316
308 317 repo_path = os.path.join(
309 318 extras.get('repo_store', ''), extras.get('repository', ''))
310 319 push_ref['hg_env'] = _get_hg_env(
311 320 old_rev=push_ref['old_rev'],
312 321 new_rev=push_ref['new_rev'], txnid=kwargs.get('txnid'),
313 322 repo_path=repo_path)
314 323
315 324 extras['hook_type'] = kwargs.get('hooktype', 'pre_push')
316 325 extras['commit_ids'] = rev_data
317 326
318 327 return _call_hook('pre_push', extras, HgMessageWriter(ui))
319 328
320 329
321 330 def pre_push_ssh(ui, repo, node=None, **kwargs):
322 331 extras = _extras_from_ui(ui)
323 332 if extras.get('SSH'):
324 333 return pre_push(ui, repo, node, **kwargs)
325 334
326 335 return 0
327 336
328 337
329 338 def pre_push_ssh_auth(ui, repo, node=None, **kwargs):
330 339 """
331 340 Mercurial pre_push hook for SSH
332 341 """
333 342 extras = _extras_from_ui(ui)
334 343 if extras.get('SSH'):
335 344 permission = extras['SSH_PERMISSIONS']
336 345
337 346 if 'repository.write' == permission or 'repository.admin' == permission:
338 347 return 0
339 348
340 349 # non-zero ret code
341 350 return 1
342 351
343 352 return 0
344 353
345 354
346 355 def post_push(ui, repo, node, **kwargs):
347 356 """
348 357 Mercurial post_push hook
349 358 """
350 359 extras = _extras_from_ui(ui)
351 360
352 361 commit_ids = []
353 362 branches = []
354 363 bookmarks = []
355 364 tags = []
356 365
357 366 commits, _heads = _rev_range_hash(repo, node)
358 367 for commit_id, branch in commits:
359 368 commit_ids.append(commit_id)
360 369 if branch not in branches:
361 370 branches.append(branch)
362 371
363 372 if hasattr(ui, '_rc_pushkey_branches'):
364 373 bookmarks = ui._rc_pushkey_branches
365 374
366 375 extras['hook_type'] = kwargs.get('hooktype', 'post_push')
367 376 extras['commit_ids'] = commit_ids
368 377 extras['new_refs'] = {
369 378 'branches': branches,
370 379 'bookmarks': bookmarks,
371 380 'tags': tags
372 381 }
373 382
374 383 return _call_hook('post_push', extras, HgMessageWriter(ui))
375 384
376 385
377 386 def post_push_ssh(ui, repo, node, **kwargs):
378 387 """
379 388 Mercurial post_push hook for SSH
380 389 """
381 390 if _extras_from_ui(ui).get('SSH'):
382 391 return post_push(ui, repo, node, **kwargs)
383 392 return 0
384 393
385 394
386 395 def key_push(ui, repo, **kwargs):
387 396 if kwargs['new'] != '0' and kwargs['namespace'] == 'bookmarks':
388 397 # store new bookmarks in our UI object propagated later to post_push
389 398 ui._rc_pushkey_branches = get_ctx(repo, kwargs['key']).bookmarks()
390 399 return
391 400
392 401
393 402 # backward compat
394 403 log_pull_action = post_pull
395 404
396 405 # backward compat
397 406 log_push_action = post_push
398 407
399 408
400 409 def handle_git_pre_receive(unused_repo_path, unused_revs, unused_env):
401 410 """
402 411 Old hook name: keep here for backward compatibility.
403 412
404 413 This is only required when the installed git hooks are not upgraded.
405 414 """
406 415 pass
407 416
408 417
409 418 def handle_git_post_receive(unused_repo_path, unused_revs, unused_env):
410 419 """
411 420 Old hook name: keep here for backward compatibility.
412 421
413 422 This is only required when the installed git hooks are not upgraded.
414 423 """
415 424 pass
416 425
417 426
418 427 HookResponse = collections.namedtuple('HookResponse', ('status', 'output'))
419 428
420 429
421 430 def git_pre_pull(extras):
422 431 """
423 432 Pre pull hook.
424 433
425 434 :param extras: dictionary containing the keys defined in simplevcs
426 435 :type extras: dict
427 436
428 437 :return: status code of the hook. 0 for success.
429 438 :rtype: int
430 439 """
431 440 if 'pull' not in extras['hooks']:
432 441 return HookResponse(0, '')
433 442
434 443 stdout = io.BytesIO()
435 444 try:
436 445 status = _call_hook('pre_pull', extras, GitMessageWriter(stdout))
437 446 except Exception as error:
438 447 status = 128
439 448 stdout.write('ERROR: %s\n' % str(error))
440 449
441 450 return HookResponse(status, stdout.getvalue())
442 451
443 452
444 453 def git_post_pull(extras):
445 454 """
446 455 Post pull hook.
447 456
448 457 :param extras: dictionary containing the keys defined in simplevcs
449 458 :type extras: dict
450 459
451 460 :return: status code of the hook. 0 for success.
452 461 :rtype: int
453 462 """
454 463 if 'pull' not in extras['hooks']:
455 464 return HookResponse(0, '')
456 465
457 466 stdout = io.BytesIO()
458 467 try:
459 468 status = _call_hook('post_pull', extras, GitMessageWriter(stdout))
460 469 except Exception as error:
461 470 status = 128
462 471 stdout.write('ERROR: %s\n' % error)
463 472
464 473 return HookResponse(status, stdout.getvalue())
465 474
466 475
467 476 def _parse_git_ref_lines(revision_lines):
468 477 rev_data = []
469 478 for revision_line in revision_lines or []:
470 479 old_rev, new_rev, ref = revision_line.strip().split(' ')
471 480 ref_data = ref.split('/', 2)
472 481 if ref_data[1] in ('tags', 'heads'):
473 482 rev_data.append({
474 483 # NOTE(marcink):
475 484 # we're unable to tell total_commits for git at this point
476 485 # but we set the variable for consistency with GIT
477 486 'total_commits': -1,
478 487 'old_rev': old_rev,
479 488 'new_rev': new_rev,
480 489 'ref': ref,
481 490 'type': ref_data[1],
482 491 'name': ref_data[2],
483 492 })
484 493 return rev_data
485 494
486 495
487 496 def git_pre_receive(unused_repo_path, revision_lines, env):
488 497 """
489 498 Pre push hook.
490 499
491 500 :param extras: dictionary containing the keys defined in simplevcs
492 501 :type extras: dict
493 502
494 503 :return: status code of the hook. 0 for success.
495 504 :rtype: int
496 505 """
497 506 extras = json.loads(env['RC_SCM_DATA'])
498 507 rev_data = _parse_git_ref_lines(revision_lines)
499 508 if 'push' not in extras['hooks']:
500 509 return 0
501 510 empty_commit_id = '0' * 40
502 511
503 512 detect_force_push = extras.get('detect_force_push')
504 513
505 514 for push_ref in rev_data:
506 515 # store our git-env which holds the temp store
507 516 push_ref['git_env'] = _get_git_env()
508 517 push_ref['pruned_sha'] = ''
509 518 if not detect_force_push:
510 519 # don't check for forced-push when we don't need to
511 520 continue
512 521
513 522 type_ = push_ref['type']
514 523 new_branch = push_ref['old_rev'] == empty_commit_id
515 524 delete_branch = push_ref['new_rev'] == empty_commit_id
516 525 if type_ == 'heads' and not (new_branch or delete_branch):
517 526 old_rev = push_ref['old_rev']
518 527 new_rev = push_ref['new_rev']
519 528 cmd = [settings.GIT_EXECUTABLE, 'rev-list', old_rev, '^{}'.format(new_rev)]
520 529 stdout, stderr = subprocessio.run_command(
521 530 cmd, env=os.environ.copy())
522 531 # means we're having some non-reachable objects, this forced push was used
523 532 if stdout:
524 533 push_ref['pruned_sha'] = stdout.splitlines()
525 534
526 535 extras['hook_type'] = 'pre_receive'
527 536 extras['commit_ids'] = rev_data
528 537 return _call_hook('pre_push', extras, GitMessageWriter())
529 538
530 539
531 540 def git_post_receive(unused_repo_path, revision_lines, env):
532 541 """
533 542 Post push hook.
534 543
535 544 :param extras: dictionary containing the keys defined in simplevcs
536 545 :type extras: dict
537 546
538 547 :return: status code of the hook. 0 for success.
539 548 :rtype: int
540 549 """
541 550 extras = json.loads(env['RC_SCM_DATA'])
542 551 if 'push' not in extras['hooks']:
543 552 return 0
544 553
545 554 rev_data = _parse_git_ref_lines(revision_lines)
546 555
547 556 git_revs = []
548 557
549 558 # N.B.(skreft): it is ok to just call git, as git before calling a
550 559 # subcommand sets the PATH environment variable so that it point to the
551 560 # correct version of the git executable.
552 561 empty_commit_id = '0' * 40
553 562 branches = []
554 563 tags = []
555 564 for push_ref in rev_data:
556 565 type_ = push_ref['type']
557 566
558 567 if type_ == 'heads':
559 568 if push_ref['old_rev'] == empty_commit_id:
560 569 # starting new branch case
561 570 if push_ref['name'] not in branches:
562 571 branches.append(push_ref['name'])
563 572
564 573 # Fix up head revision if needed
565 574 cmd = [settings.GIT_EXECUTABLE, 'show', 'HEAD']
566 575 try:
567 576 subprocessio.run_command(cmd, env=os.environ.copy())
568 577 except Exception:
569 578 cmd = [settings.GIT_EXECUTABLE, 'symbolic-ref', 'HEAD',
570 579 'refs/heads/%s' % push_ref['name']]
571 580 print("Setting default branch to %s" % push_ref['name'])
572 581 subprocessio.run_command(cmd, env=os.environ.copy())
573 582
574 583 cmd = [settings.GIT_EXECUTABLE, 'for-each-ref',
575 584 '--format=%(refname)', 'refs/heads/*']
576 585 stdout, stderr = subprocessio.run_command(
577 586 cmd, env=os.environ.copy())
578 587 heads = stdout
579 588 heads = heads.replace(push_ref['ref'], '')
580 589 heads = ' '.join(head for head
581 590 in heads.splitlines() if head) or '.'
582 591 cmd = [settings.GIT_EXECUTABLE, 'log', '--reverse',
583 592 '--pretty=format:%H', '--', push_ref['new_rev'],
584 593 '--not', heads]
585 594 stdout, stderr = subprocessio.run_command(
586 595 cmd, env=os.environ.copy())
587 596 git_revs.extend(stdout.splitlines())
588 597 elif push_ref['new_rev'] == empty_commit_id:
589 598 # delete branch case
590 599 git_revs.append('delete_branch=>%s' % push_ref['name'])
591 600 else:
592 601 if push_ref['name'] not in branches:
593 602 branches.append(push_ref['name'])
594 603
595 604 cmd = [settings.GIT_EXECUTABLE, 'log',
596 605 '{old_rev}..{new_rev}'.format(**push_ref),
597 606 '--reverse', '--pretty=format:%H']
598 607 stdout, stderr = subprocessio.run_command(
599 608 cmd, env=os.environ.copy())
600 609 git_revs.extend(stdout.splitlines())
601 610 elif type_ == 'tags':
602 611 if push_ref['name'] not in tags:
603 612 tags.append(push_ref['name'])
604 613 git_revs.append('tag=>%s' % push_ref['name'])
605 614
606 615 extras['hook_type'] = 'post_receive'
607 616 extras['commit_ids'] = git_revs
608 617 extras['new_refs'] = {
609 618 'branches': branches,
610 619 'bookmarks': [],
611 620 'tags': tags,
612 621 }
613 622
614 623 if 'repo_size' in extras['hooks']:
615 624 try:
616 625 _call_hook('repo_size', extras, GitMessageWriter())
617 626 except:
618 627 pass
619 628
620 629 return _call_hook('post_push', extras, GitMessageWriter())
621 630
622 631
623 632 def _get_extras_from_txn_id(path, txn_id):
624 633 extras = {}
625 634 try:
626 635 cmd = [settings.SVNLOOK_EXECUTABLE, 'pget',
627 636 '-t', txn_id,
628 637 '--revprop', path, 'rc-scm-extras']
629 638 stdout, stderr = subprocessio.run_command(
630 639 cmd, env=os.environ.copy())
631 640 extras = json.loads(base64.urlsafe_b64decode(stdout))
632 641 except Exception:
633 642 log.exception('Failed to extract extras info from txn_id')
634 643
635 644 return extras
636 645
637 646
638 647 def _get_extras_from_commit_id(commit_id, path):
639 648 extras = {}
640 649 try:
641 650 cmd = [settings.SVNLOOK_EXECUTABLE, 'pget',
642 651 '-r', commit_id,
643 652 '--revprop', path, 'rc-scm-extras']
644 653 stdout, stderr = subprocessio.run_command(
645 654 cmd, env=os.environ.copy())
646 655 extras = json.loads(base64.urlsafe_b64decode(stdout))
647 656 except Exception:
648 657 log.exception('Failed to extract extras info from commit_id')
649 658
650 659 return extras
651 660
652 661
653 662 def svn_pre_commit(repo_path, commit_data, env):
654 663 path, txn_id = commit_data
655 664 branches = []
656 665 tags = []
657 666
658 667 if env.get('RC_SCM_DATA'):
659 668 extras = json.loads(env['RC_SCM_DATA'])
660 669 else:
661 670 # fallback method to read from TXN-ID stored data
662 671 extras = _get_extras_from_txn_id(path, txn_id)
663 672 if not extras:
664 673 return 0
665 674
666 675 extras['hook_type'] = 'pre_commit'
667 676 extras['commit_ids'] = [txn_id]
668 677 extras['txn_id'] = txn_id
669 678 extras['new_refs'] = {
670 679 'total_commits': 1,
671 680 'branches': branches,
672 681 'bookmarks': [],
673 682 'tags': tags,
674 683 }
675 684
676 685 return _call_hook('pre_push', extras, SvnMessageWriter())
677 686
678 687
679 688 def svn_post_commit(repo_path, commit_data, env):
680 689 """
681 690 commit_data is path, rev, txn_id
682 691 """
683 692 path, commit_id, txn_id = commit_data
684 693 branches = []
685 694 tags = []
686 695
687 696 if env.get('RC_SCM_DATA'):
688 697 extras = json.loads(env['RC_SCM_DATA'])
689 698 else:
690 699 # fallback method to read from TXN-ID stored data
691 700 extras = _get_extras_from_commit_id(commit_id, path)
692 701 if not extras:
693 702 return 0
694 703
695 704 extras['hook_type'] = 'post_commit'
696 705 extras['commit_ids'] = [commit_id]
697 706 extras['txn_id'] = txn_id
698 707 extras['new_refs'] = {
699 708 'branches': branches,
700 709 'bookmarks': [],
701 710 'tags': tags,
702 711 'total_commits': 1,
703 712 }
704 713
705 714 if 'repo_size' in extras['hooks']:
706 715 try:
707 716 _call_hook('repo_size', extras, SvnMessageWriter())
708 717 except Exception:
709 718 pass
710 719
711 720 return _call_hook('post_push', extras, SvnMessageWriter())
General Comments 0
You need to be logged in to leave comments. Login now