##// END OF EJS Templates
release: merge back stable branch into default
marcink -
r585:54713335 merge default
parent child Browse files
Show More
@@ -1,47 +1,48 b''
1 c6fad7d1e61f22b1f4a4863eff207a04c27e9462 v4.0.0
1 c6fad7d1e61f22b1f4a4863eff207a04c27e9462 v4.0.0
2 77b6e243b4cc5b702c15abd6d737798edbac60dc v4.0.1
2 77b6e243b4cc5b702c15abd6d737798edbac60dc v4.0.1
3 a359c072337fdd8e1e71df72cc520b8a9b042f80 v4.1.0
3 a359c072337fdd8e1e71df72cc520b8a9b042f80 v4.1.0
4 49aa7ed030a36b7ceba149a21e587cb5d20b4946 v4.1.1
4 49aa7ed030a36b7ceba149a21e587cb5d20b4946 v4.1.1
5 f38ed1e1a31dce3c170b4d31585ba43471cf0705 v4.1.2
5 f38ed1e1a31dce3c170b4d31585ba43471cf0705 v4.1.2
6 21269ba7bafd8f0c77e79dd86a31eb9bce7643d2 v4.2.0
6 21269ba7bafd8f0c77e79dd86a31eb9bce7643d2 v4.2.0
7 b53930c918c25b2c8f69ceddc6641e511be27fd3 v4.2.1
7 b53930c918c25b2c8f69ceddc6641e511be27fd3 v4.2.1
8 6627ff4119723d8b2b60918e8b1aa49e9f055aab v4.3.0
8 6627ff4119723d8b2b60918e8b1aa49e9f055aab v4.3.0
9 d38f2c2b861dde6c4178923f7cf15ea58b85aa92 v4.3.1
9 d38f2c2b861dde6c4178923f7cf15ea58b85aa92 v4.3.1
10 1232313f9e6adac5ce5399c2a891dc1e72b79022 v4.4.0
10 1232313f9e6adac5ce5399c2a891dc1e72b79022 v4.4.0
11 cbb9f1d329ae5768379cdec55a62ebdd546c4e27 v4.4.1
11 cbb9f1d329ae5768379cdec55a62ebdd546c4e27 v4.4.1
12 24ffe44a27fcd1c5b6936144e176b9f6dd2f3a17 v4.4.2
12 24ffe44a27fcd1c5b6936144e176b9f6dd2f3a17 v4.4.2
13 beaeeaa440cd17471110d4621b8816506c0dff4a v4.5.0
13 beaeeaa440cd17471110d4621b8816506c0dff4a v4.5.0
14 668e5c656f61dd94595611844e1106d1361aa6a7 v4.5.1
14 668e5c656f61dd94595611844e1106d1361aa6a7 v4.5.1
15 ae0640240cb7a77e6dc8c77e64dd80d79732cb5b v4.5.2
15 ae0640240cb7a77e6dc8c77e64dd80d79732cb5b v4.5.2
16 7af06899f426813583fe60449d7517cc49c15b28 v4.6.0
16 7af06899f426813583fe60449d7517cc49c15b28 v4.6.0
17 8f7f4299bf341b43f94dadafa1ea73d6cea2c9ba v4.6.1
17 8f7f4299bf341b43f94dadafa1ea73d6cea2c9ba v4.6.1
18 de00a831a0709ffaac57f948738ea927b97223a9 v4.7.0
18 de00a831a0709ffaac57f948738ea927b97223a9 v4.7.0
19 57f527e0646d731768fb5e0fe742b12a35bdc63b v4.7.1
19 57f527e0646d731768fb5e0fe742b12a35bdc63b v4.7.1
20 f9b09787da9845e4a105f4bffdc252099902cefb v4.7.2
20 f9b09787da9845e4a105f4bffdc252099902cefb v4.7.2
21 0b7c790b726f08385e6ebdf4f257c905787b9244 v4.8.0
21 0b7c790b726f08385e6ebdf4f257c905787b9244 v4.8.0
22 f4123e725b74d0e82fe89982ab8791a66062e2b3 v4.9.0
22 f4123e725b74d0e82fe89982ab8791a66062e2b3 v4.9.0
23 940bac044a0fe1ec839759df81399b50141be720 v4.9.1
23 940bac044a0fe1ec839759df81399b50141be720 v4.9.1
24 582d9ebbe46bdddac4b26eacae36ee5ecabca267 v4.10.0
24 582d9ebbe46bdddac4b26eacae36ee5ecabca267 v4.10.0
25 12fbd08d0ab57acce9c0bdccee75633cfa08d7f4 v4.10.1
25 12fbd08d0ab57acce9c0bdccee75633cfa08d7f4 v4.10.1
26 78352f95021a9d128f5803fdbca7036daef5dabe v4.10.2
26 78352f95021a9d128f5803fdbca7036daef5dabe v4.10.2
27 a47ccfb020cda78c8680e3844aaf0b82b1390f3b v4.10.3
27 a47ccfb020cda78c8680e3844aaf0b82b1390f3b v4.10.3
28 347ae9ae544bba8deb417995285287a3b6be1611 v4.10.4
28 347ae9ae544bba8deb417995285287a3b6be1611 v4.10.4
29 9b257ac49841f850434be0d518baca0827e6c8cc v4.10.5
29 9b257ac49841f850434be0d518baca0827e6c8cc v4.10.5
30 e8bf26eea118694edc4ffe50c6c5aa91022bc434 v4.10.6
30 e8bf26eea118694edc4ffe50c6c5aa91022bc434 v4.10.6
31 71fa9274ba59fb982104f0b9b3d0d024c78675f7 v4.11.0
31 71fa9274ba59fb982104f0b9b3d0d024c78675f7 v4.11.0
32 92471577ef25636e5babe8001d47fc8e51521522 v4.11.1
32 92471577ef25636e5babe8001d47fc8e51521522 v4.11.1
33 0277edbcda5a8d075e1e41a95bcee6dcf21f3f77 v4.11.2
33 0277edbcda5a8d075e1e41a95bcee6dcf21f3f77 v4.11.2
34 6c5ecbf0778ef870e5b23d9fad5340135b563356 v4.11.3
34 6c5ecbf0778ef870e5b23d9fad5340135b563356 v4.11.3
35 be788a89a939ebd63606220064bd624fa9d5c9c9 v4.11.4
35 be788a89a939ebd63606220064bd624fa9d5c9c9 v4.11.4
36 15c90a04098a373ac761fab07695fd80dde3bcdb v4.11.5
36 15c90a04098a373ac761fab07695fd80dde3bcdb v4.11.5
37 77aff155b3251cc00394a49f5e8f2c99e33149a7 v4.11.6
37 77aff155b3251cc00394a49f5e8f2c99e33149a7 v4.11.6
38 c218a1ce5d370c2e671d42a91684b3fc2c91b81d v4.12.0
38 c218a1ce5d370c2e671d42a91684b3fc2c91b81d v4.12.0
39 80085fb846cc948195a5c76b579ca34cbc49b59b v4.12.1
39 80085fb846cc948195a5c76b579ca34cbc49b59b v4.12.1
40 346f04fc8a18df3235defbe6e71bd552c0d46481 v4.12.2
40 346f04fc8a18df3235defbe6e71bd552c0d46481 v4.12.2
41 764fdd752322f3e0c13ea00957f2d548bf4363a7 v4.12.3
41 764fdd752322f3e0c13ea00957f2d548bf4363a7 v4.12.3
42 b58038974a5cecbb9c100d32ad2e4c68582f1a78 v4.12.4
42 b58038974a5cecbb9c100d32ad2e4c68582f1a78 v4.12.4
43 e1d42d92a0fec0c80b56c82f37bc7b5472613706 v4.13.0
43 e1d42d92a0fec0c80b56c82f37bc7b5472613706 v4.13.0
44 c3ded3ff17e9bb2a47002a808984a7a946f58a1c v4.13.1
44 c3ded3ff17e9bb2a47002a808984a7a946f58a1c v4.13.1
45 7ff81aa47b1b40cdef9dd5bcdd439f59c269db3d v4.13.2
45 7ff81aa47b1b40cdef9dd5bcdd439f59c269db3d v4.13.2
46 628a08e6aaeff2c3f9e0e268e854f870e6778e53 v4.13.3
46 628a08e6aaeff2c3f9e0e268e854f870e6778e53 v4.13.3
47 941d675f10cfa7d774815bfacfb37085751b7a0d v4.14.0
47 941d675f10cfa7d774815bfacfb37085751b7a0d v4.14.0
48 75e11d32c0be0a457198f07888e7ef650cfa6888 v4.14.1
@@ -1,700 +1,702 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 == 'HTTPBranchProtected':
124 elif exception_class == 'HTTPBranchProtected':
125 raise exceptions.RepositoryBranchProtectedException()(*result['exception_args'])
125 raise exceptions.RepositoryBranchProtectedException()(*result['exception_args'])
126 elif exception_class == 'RepositoryError':
126 elif exception_class == 'RepositoryError':
127 raise exceptions.VcsException()(*result['exception_args'])
127 raise exceptions.VcsException()(*result['exception_args'])
128 elif exception_class:
128 elif exception_class:
129 raise Exception('Got remote exception "%s" with args "%s"' %
129 raise Exception('Got remote exception "%s" with args "%s"' %
130 (exception_class, result['exception_args']))
130 (exception_class, result['exception_args']))
131
131
132
132
133 def _get_hooks_client(extras):
133 def _get_hooks_client(extras):
134 if 'hooks_uri' in extras:
134 if 'hooks_uri' in extras:
135 protocol = extras.get('hooks_protocol')
135 protocol = extras.get('hooks_protocol')
136 return HooksHttpClient(extras['hooks_uri'])
136 return HooksHttpClient(extras['hooks_uri'])
137 else:
137 else:
138 return HooksDummyClient(extras['hooks_module'])
138 return HooksDummyClient(extras['hooks_module'])
139
139
140
140
141 def _call_hook(hook_name, extras, writer):
141 def _call_hook(hook_name, extras, writer):
142 hooks_client = _get_hooks_client(extras)
142 hooks_client = _get_hooks_client(extras)
143 log.debug('Hooks, using client:%s', hooks_client)
143 log.debug('Hooks, using client:%s', hooks_client)
144 result = hooks_client(hook_name, extras)
144 result = hooks_client(hook_name, extras)
145 log.debug('Hooks got result: %s', result)
145 log.debug('Hooks got result: %s', result)
146
146
147 _handle_exception(result)
147 _handle_exception(result)
148 writer.write(result['output'])
148 writer.write(result['output'])
149
149
150 return result['status']
150 return result['status']
151
151
152
152
153 def _extras_from_ui(ui):
153 def _extras_from_ui(ui):
154 hook_data = ui.config('rhodecode', 'RC_SCM_DATA')
154 hook_data = ui.config('rhodecode', 'RC_SCM_DATA')
155 if not hook_data:
155 if not hook_data:
156 # maybe it's inside environ ?
156 # maybe it's inside environ ?
157 env_hook_data = os.environ.get('RC_SCM_DATA')
157 env_hook_data = os.environ.get('RC_SCM_DATA')
158 if env_hook_data:
158 if env_hook_data:
159 hook_data = env_hook_data
159 hook_data = env_hook_data
160
160
161 extras = {}
161 extras = {}
162 if hook_data:
162 if hook_data:
163 extras = json.loads(hook_data)
163 extras = json.loads(hook_data)
164 return extras
164 return extras
165
165
166
166
167 def _rev_range_hash(repo, node, check_heads=False):
167 def _rev_range_hash(repo, node, check_heads=False):
168
168
169 commits = []
169 commits = []
170 revs = []
170 revs = []
171 start = repo[node].rev()
171 start = repo[node].rev()
172 end = len(repo)
172 end = len(repo)
173 for rev in range(start, end):
173 for rev in range(start, end):
174 revs.append(rev)
174 revs.append(rev)
175 ctx = repo[rev]
175 ctx = repo[rev]
176 commit_id = mercurial.node.hex(ctx.node())
176 commit_id = mercurial.node.hex(ctx.node())
177 branch = ctx.branch()
177 branch = ctx.branch()
178 commits.append((commit_id, branch))
178 commits.append((commit_id, branch))
179
179
180 parent_heads = []
180 parent_heads = []
181 if check_heads:
181 if check_heads:
182 parent_heads = _check_heads(repo, start, end, revs)
182 parent_heads = _check_heads(repo, start, end, revs)
183 return commits, parent_heads
183 return commits, parent_heads
184
184
185
185
186 def _check_heads(repo, start, end, commits):
186 def _check_heads(repo, start, end, commits):
187 changelog = repo.changelog
187 changelog = repo.changelog
188 parents = set()
188 parents = set()
189
189
190 for new_rev in commits:
190 for new_rev in commits:
191 for p in changelog.parentrevs(new_rev):
191 for p in changelog.parentrevs(new_rev):
192 if p == mercurial.node.nullrev:
192 if p == mercurial.node.nullrev:
193 continue
193 continue
194 if p < start:
194 if p < start:
195 parents.add(p)
195 parents.add(p)
196
196
197 for p in parents:
197 for p in parents:
198 branch = repo[p].branch()
198 branch = repo[p].branch()
199 # The heads descending from that parent, on the same branch
199 # The heads descending from that parent, on the same branch
200 parent_heads = set([p])
200 parent_heads = set([p])
201 reachable = set([p])
201 reachable = set([p])
202 for x in xrange(p + 1, end):
202 for x in xrange(p + 1, end):
203 if repo[x].branch() != branch:
203 if repo[x].branch() != branch:
204 continue
204 continue
205 for pp in changelog.parentrevs(x):
205 for pp in changelog.parentrevs(x):
206 if pp in reachable:
206 if pp in reachable:
207 reachable.add(x)
207 reachable.add(x)
208 parent_heads.discard(pp)
208 parent_heads.discard(pp)
209 parent_heads.add(x)
209 parent_heads.add(x)
210 # More than one head? Suggest merging
210 # More than one head? Suggest merging
211 if len(parent_heads) > 1:
211 if len(parent_heads) > 1:
212 return list(parent_heads)
212 return list(parent_heads)
213
213
214 return []
214 return []
215
215
216
216
217 def _get_git_env():
217 def _get_git_env():
218 env = {}
218 env = {}
219 for k, v in os.environ.items():
219 for k, v in os.environ.items():
220 if k.startswith('GIT'):
220 if k.startswith('GIT'):
221 env[k] = v
221 env[k] = v
222
222
223 # serialized version
223 # serialized version
224 return [(k, v) for k, v in env.items()]
224 return [(k, v) for k, v in env.items()]
225
225
226
226
227 def _get_hg_env(old_rev, new_rev, txnid, repo_path):
227 def _get_hg_env(old_rev, new_rev, txnid, repo_path):
228 env = {}
228 env = {}
229 for k, v in os.environ.items():
229 for k, v in os.environ.items():
230 if k.startswith('HG'):
230 if k.startswith('HG'):
231 env[k] = v
231 env[k] = v
232
232
233 env['HG_NODE'] = old_rev
233 env['HG_NODE'] = old_rev
234 env['HG_NODE_LAST'] = new_rev
234 env['HG_NODE_LAST'] = new_rev
235 env['HG_TXNID'] = txnid
235 env['HG_TXNID'] = txnid
236 env['HG_PENDING'] = repo_path
236 env['HG_PENDING'] = repo_path
237
237
238 return [(k, v) for k, v in env.items()]
238 return [(k, v) for k, v in env.items()]
239
239
240
240
241 def repo_size(ui, repo, **kwargs):
241 def repo_size(ui, repo, **kwargs):
242 extras = _extras_from_ui(ui)
242 extras = _extras_from_ui(ui)
243 return _call_hook('repo_size', extras, HgMessageWriter(ui))
243 return _call_hook('repo_size', extras, HgMessageWriter(ui))
244
244
245
245
246 def pre_pull(ui, repo, **kwargs):
246 def pre_pull(ui, repo, **kwargs):
247 extras = _extras_from_ui(ui)
247 extras = _extras_from_ui(ui)
248 return _call_hook('pre_pull', extras, HgMessageWriter(ui))
248 return _call_hook('pre_pull', extras, HgMessageWriter(ui))
249
249
250
250
251 def pre_pull_ssh(ui, repo, **kwargs):
251 def pre_pull_ssh(ui, repo, **kwargs):
252 extras = _extras_from_ui(ui)
252 extras = _extras_from_ui(ui)
253 if extras and extras.get('SSH'):
253 if extras and extras.get('SSH'):
254 return pre_pull(ui, repo, **kwargs)
254 return pre_pull(ui, repo, **kwargs)
255 return 0
255 return 0
256
256
257
257
258 def post_pull(ui, repo, **kwargs):
258 def post_pull(ui, repo, **kwargs):
259 extras = _extras_from_ui(ui)
259 extras = _extras_from_ui(ui)
260 return _call_hook('post_pull', extras, HgMessageWriter(ui))
260 return _call_hook('post_pull', extras, HgMessageWriter(ui))
261
261
262
262
263 def post_pull_ssh(ui, repo, **kwargs):
263 def post_pull_ssh(ui, repo, **kwargs):
264 extras = _extras_from_ui(ui)
264 extras = _extras_from_ui(ui)
265 if extras and extras.get('SSH'):
265 if extras and extras.get('SSH'):
266 return post_pull(ui, repo, **kwargs)
266 return post_pull(ui, repo, **kwargs)
267 return 0
267 return 0
268
268
269
269
270 def pre_push(ui, repo, node=None, **kwargs):
270 def pre_push(ui, repo, node=None, **kwargs):
271 """
271 """
272 Mercurial pre_push hook
272 Mercurial pre_push hook
273 """
273 """
274 extras = _extras_from_ui(ui)
274 extras = _extras_from_ui(ui)
275 detect_force_push = extras.get('detect_force_push')
275 detect_force_push = extras.get('detect_force_push')
276
276
277 rev_data = []
277 rev_data = []
278 if node and kwargs.get('hooktype') == 'pretxnchangegroup':
278 if node and kwargs.get('hooktype') == 'pretxnchangegroup':
279 branches = collections.defaultdict(list)
279 branches = collections.defaultdict(list)
280 commits, _heads = _rev_range_hash(repo, node, check_heads=detect_force_push)
280 commits, _heads = _rev_range_hash(repo, node, check_heads=detect_force_push)
281 for commit_id, branch in commits:
281 for commit_id, branch in commits:
282 branches[branch].append(commit_id)
282 branches[branch].append(commit_id)
283
283
284 for branch, commits in branches.items():
284 for branch, commits in branches.items():
285 old_rev = kwargs.get('node_last') or commits[0]
285 old_rev = kwargs.get('node_last') or commits[0]
286 rev_data.append({
286 rev_data.append({
287 'total_commits': len(commits),
287 'total_commits': len(commits),
288 'old_rev': old_rev,
288 'old_rev': old_rev,
289 'new_rev': commits[-1],
289 'new_rev': commits[-1],
290 'ref': '',
290 'ref': '',
291 'type': 'branch',
291 'type': 'branch',
292 'name': branch,
292 'name': branch,
293 })
293 })
294
294
295 for push_ref in rev_data:
295 for push_ref in rev_data:
296 push_ref['multiple_heads'] = _heads
296 push_ref['multiple_heads'] = _heads
297
297
298 repo_path = os.path.join(
298 repo_path = os.path.join(
299 extras.get('repo_store', ''), extras.get('repository', ''))
299 extras.get('repo_store', ''), extras.get('repository', ''))
300 push_ref['hg_env'] = _get_hg_env(
300 push_ref['hg_env'] = _get_hg_env(
301 old_rev=push_ref['old_rev'],
301 old_rev=push_ref['old_rev'],
302 new_rev=push_ref['new_rev'], txnid=kwargs.get('txnid'),
302 new_rev=push_ref['new_rev'], txnid=kwargs.get('txnid'),
303 repo_path=repo_path)
303 repo_path=repo_path)
304
304
305 extras['hook_type'] = kwargs.get('hooktype', 'pre_push')
305 extras['hook_type'] = kwargs.get('hooktype', 'pre_push')
306 extras['commit_ids'] = rev_data
306 extras['commit_ids'] = rev_data
307
307
308 return _call_hook('pre_push', extras, HgMessageWriter(ui))
308 return _call_hook('pre_push', extras, HgMessageWriter(ui))
309
309
310
310
311 def pre_push_ssh(ui, repo, node=None, **kwargs):
311 def pre_push_ssh(ui, repo, node=None, **kwargs):
312 extras = _extras_from_ui(ui)
312 extras = _extras_from_ui(ui)
313 if extras.get('SSH'):
313 if extras.get('SSH'):
314 return pre_push(ui, repo, node, **kwargs)
314 return pre_push(ui, repo, node, **kwargs)
315
315
316 return 0
316 return 0
317
317
318
318
319 def pre_push_ssh_auth(ui, repo, node=None, **kwargs):
319 def pre_push_ssh_auth(ui, repo, node=None, **kwargs):
320 """
320 """
321 Mercurial pre_push hook for SSH
321 Mercurial pre_push hook for SSH
322 """
322 """
323 extras = _extras_from_ui(ui)
323 extras = _extras_from_ui(ui)
324 if extras.get('SSH'):
324 if extras.get('SSH'):
325 permission = extras['SSH_PERMISSIONS']
325 permission = extras['SSH_PERMISSIONS']
326
326
327 if 'repository.write' == permission or 'repository.admin' == permission:
327 if 'repository.write' == permission or 'repository.admin' == permission:
328 return 0
328 return 0
329
329
330 # non-zero ret code
330 # non-zero ret code
331 return 1
331 return 1
332
332
333 return 0
333 return 0
334
334
335
335
336 def post_push(ui, repo, node, **kwargs):
336 def post_push(ui, repo, node, **kwargs):
337 """
337 """
338 Mercurial post_push hook
338 Mercurial post_push hook
339 """
339 """
340 extras = _extras_from_ui(ui)
340 extras = _extras_from_ui(ui)
341
341
342 commit_ids = []
342 commit_ids = []
343 branches = []
343 branches = []
344 bookmarks = []
344 bookmarks = []
345 tags = []
345 tags = []
346
346
347 commits, _heads = _rev_range_hash(repo, node)
347 commits, _heads = _rev_range_hash(repo, node)
348 for commit_id, branch in commits:
348 for commit_id, branch in commits:
349 commit_ids.append(commit_id)
349 commit_ids.append(commit_id)
350 if branch not in branches:
350 if branch not in branches:
351 branches.append(branch)
351 branches.append(branch)
352
352
353 if hasattr(ui, '_rc_pushkey_branches'):
353 if hasattr(ui, '_rc_pushkey_branches'):
354 bookmarks = ui._rc_pushkey_branches
354 bookmarks = ui._rc_pushkey_branches
355
355
356 extras['hook_type'] = kwargs.get('hooktype', 'post_push')
356 extras['hook_type'] = kwargs.get('hooktype', 'post_push')
357 extras['commit_ids'] = commit_ids
357 extras['commit_ids'] = commit_ids
358 extras['new_refs'] = {
358 extras['new_refs'] = {
359 'branches': branches,
359 'branches': branches,
360 'bookmarks': bookmarks,
360 'bookmarks': bookmarks,
361 'tags': tags
361 'tags': tags
362 }
362 }
363
363
364 return _call_hook('post_push', extras, HgMessageWriter(ui))
364 return _call_hook('post_push', extras, HgMessageWriter(ui))
365
365
366
366
367 def post_push_ssh(ui, repo, node, **kwargs):
367 def post_push_ssh(ui, repo, node, **kwargs):
368 """
368 """
369 Mercurial post_push hook for SSH
369 Mercurial post_push hook for SSH
370 """
370 """
371 if _extras_from_ui(ui).get('SSH'):
371 if _extras_from_ui(ui).get('SSH'):
372 return post_push(ui, repo, node, **kwargs)
372 return post_push(ui, repo, node, **kwargs)
373 return 0
373 return 0
374
374
375
375
376 def key_push(ui, repo, **kwargs):
376 def key_push(ui, repo, **kwargs):
377 if kwargs['new'] != '0' and kwargs['namespace'] == 'bookmarks':
377 if kwargs['new'] != '0' and kwargs['namespace'] == 'bookmarks':
378 # store new bookmarks in our UI object propagated later to post_push
378 # store new bookmarks in our UI object propagated later to post_push
379 ui._rc_pushkey_branches = repo[kwargs['key']].bookmarks()
379 ui._rc_pushkey_branches = repo[kwargs['key']].bookmarks()
380 return
380 return
381
381
382
382
383 # backward compat
383 # backward compat
384 log_pull_action = post_pull
384 log_pull_action = post_pull
385
385
386 # backward compat
386 # backward compat
387 log_push_action = post_push
387 log_push_action = post_push
388
388
389
389
390 def handle_git_pre_receive(unused_repo_path, unused_revs, unused_env):
390 def handle_git_pre_receive(unused_repo_path, unused_revs, unused_env):
391 """
391 """
392 Old hook name: keep here for backward compatibility.
392 Old hook name: keep here for backward compatibility.
393
393
394 This is only required when the installed git hooks are not upgraded.
394 This is only required when the installed git hooks are not upgraded.
395 """
395 """
396 pass
396 pass
397
397
398
398
399 def handle_git_post_receive(unused_repo_path, unused_revs, unused_env):
399 def handle_git_post_receive(unused_repo_path, unused_revs, unused_env):
400 """
400 """
401 Old hook name: keep here for backward compatibility.
401 Old hook name: keep here for backward compatibility.
402
402
403 This is only required when the installed git hooks are not upgraded.
403 This is only required when the installed git hooks are not upgraded.
404 """
404 """
405 pass
405 pass
406
406
407
407
408 HookResponse = collections.namedtuple('HookResponse', ('status', 'output'))
408 HookResponse = collections.namedtuple('HookResponse', ('status', 'output'))
409
409
410
410
411 def git_pre_pull(extras):
411 def git_pre_pull(extras):
412 """
412 """
413 Pre pull hook.
413 Pre pull hook.
414
414
415 :param extras: dictionary containing the keys defined in simplevcs
415 :param extras: dictionary containing the keys defined in simplevcs
416 :type extras: dict
416 :type extras: dict
417
417
418 :return: status code of the hook. 0 for success.
418 :return: status code of the hook. 0 for success.
419 :rtype: int
419 :rtype: int
420 """
420 """
421 if 'pull' not in extras['hooks']:
421 if 'pull' not in extras['hooks']:
422 return HookResponse(0, '')
422 return HookResponse(0, '')
423
423
424 stdout = io.BytesIO()
424 stdout = io.BytesIO()
425 try:
425 try:
426 status = _call_hook('pre_pull', extras, GitMessageWriter(stdout))
426 status = _call_hook('pre_pull', extras, GitMessageWriter(stdout))
427 except Exception as error:
427 except Exception as error:
428 status = 128
428 status = 128
429 stdout.write('ERROR: %s\n' % str(error))
429 stdout.write('ERROR: %s\n' % str(error))
430
430
431 return HookResponse(status, stdout.getvalue())
431 return HookResponse(status, stdout.getvalue())
432
432
433
433
434 def git_post_pull(extras):
434 def git_post_pull(extras):
435 """
435 """
436 Post pull hook.
436 Post pull hook.
437
437
438 :param extras: dictionary containing the keys defined in simplevcs
438 :param extras: dictionary containing the keys defined in simplevcs
439 :type extras: dict
439 :type extras: dict
440
440
441 :return: status code of the hook. 0 for success.
441 :return: status code of the hook. 0 for success.
442 :rtype: int
442 :rtype: int
443 """
443 """
444 if 'pull' not in extras['hooks']:
444 if 'pull' not in extras['hooks']:
445 return HookResponse(0, '')
445 return HookResponse(0, '')
446
446
447 stdout = io.BytesIO()
447 stdout = io.BytesIO()
448 try:
448 try:
449 status = _call_hook('post_pull', extras, GitMessageWriter(stdout))
449 status = _call_hook('post_pull', extras, GitMessageWriter(stdout))
450 except Exception as error:
450 except Exception as error:
451 status = 128
451 status = 128
452 stdout.write('ERROR: %s\n' % error)
452 stdout.write('ERROR: %s\n' % error)
453
453
454 return HookResponse(status, stdout.getvalue())
454 return HookResponse(status, stdout.getvalue())
455
455
456
456
457 def _parse_git_ref_lines(revision_lines):
457 def _parse_git_ref_lines(revision_lines):
458 rev_data = []
458 rev_data = []
459 for revision_line in revision_lines or []:
459 for revision_line in revision_lines or []:
460 old_rev, new_rev, ref = revision_line.strip().split(' ')
460 old_rev, new_rev, ref = revision_line.strip().split(' ')
461 ref_data = ref.split('/', 2)
461 ref_data = ref.split('/', 2)
462 if ref_data[1] in ('tags', 'heads'):
462 if ref_data[1] in ('tags', 'heads'):
463 rev_data.append({
463 rev_data.append({
464 # NOTE(marcink):
464 # NOTE(marcink):
465 # we're unable to tell total_commits for git at this point
465 # we're unable to tell total_commits for git at this point
466 # but we set the variable for consistency with GIT
466 # but we set the variable for consistency with GIT
467 'total_commits': -1,
467 'total_commits': -1,
468 'old_rev': old_rev,
468 'old_rev': old_rev,
469 'new_rev': new_rev,
469 'new_rev': new_rev,
470 'ref': ref,
470 'ref': ref,
471 'type': ref_data[1],
471 'type': ref_data[1],
472 'name': ref_data[2],
472 'name': ref_data[2],
473 })
473 })
474 return rev_data
474 return rev_data
475
475
476
476
477 def git_pre_receive(unused_repo_path, revision_lines, env):
477 def git_pre_receive(unused_repo_path, revision_lines, env):
478 """
478 """
479 Pre push hook.
479 Pre push hook.
480
480
481 :param extras: dictionary containing the keys defined in simplevcs
481 :param extras: dictionary containing the keys defined in simplevcs
482 :type extras: dict
482 :type extras: dict
483
483
484 :return: status code of the hook. 0 for success.
484 :return: status code of the hook. 0 for success.
485 :rtype: int
485 :rtype: int
486 """
486 """
487 extras = json.loads(env['RC_SCM_DATA'])
487 extras = json.loads(env['RC_SCM_DATA'])
488 rev_data = _parse_git_ref_lines(revision_lines)
488 rev_data = _parse_git_ref_lines(revision_lines)
489 if 'push' not in extras['hooks']:
489 if 'push' not in extras['hooks']:
490 return 0
490 return 0
491 empty_commit_id = '0' * 40
491 empty_commit_id = '0' * 40
492
492
493 detect_force_push = extras.get('detect_force_push')
493 detect_force_push = extras.get('detect_force_push')
494
494
495 for push_ref in rev_data:
495 for push_ref in rev_data:
496 # store our git-env which holds the temp store
496 # store our git-env which holds the temp store
497 push_ref['git_env'] = _get_git_env()
497 push_ref['git_env'] = _get_git_env()
498 push_ref['pruned_sha'] = ''
498 push_ref['pruned_sha'] = ''
499 if not detect_force_push:
499 if not detect_force_push:
500 # don't check for forced-push when we don't need to
500 # don't check for forced-push when we don't need to
501 continue
501 continue
502
502
503 type_ = push_ref['type']
503 type_ = push_ref['type']
504 new_branch = push_ref['old_rev'] == empty_commit_id
504 new_branch = push_ref['old_rev'] == empty_commit_id
505 if type_ == 'heads' and not new_branch:
505 if type_ == 'heads' and not new_branch:
506 old_rev = push_ref['old_rev']
506 old_rev = push_ref['old_rev']
507 new_rev = push_ref['new_rev']
507 new_rev = push_ref['new_rev']
508 cmd = [settings.GIT_EXECUTABLE, 'rev-list',
508 cmd = [settings.GIT_EXECUTABLE, 'rev-list',
509 old_rev, '^{}'.format(new_rev)]
509 old_rev, '^{}'.format(new_rev)]
510 stdout, stderr = subprocessio.run_command(
510 stdout, stderr = subprocessio.run_command(
511 cmd, env=os.environ.copy())
511 cmd, env=os.environ.copy())
512 # means we're having some non-reachable objects, this forced push
512 # means we're having some non-reachable objects, this forced push
513 # was used
513 # was used
514 if stdout:
514 if stdout:
515 push_ref['pruned_sha'] = stdout.splitlines()
515 push_ref['pruned_sha'] = stdout.splitlines()
516
516
517 extras['hook_type'] = 'pre_receive'
517 extras['hook_type'] = 'pre_receive'
518 extras['commit_ids'] = rev_data
518 extras['commit_ids'] = rev_data
519 return _call_hook('pre_push', extras, GitMessageWriter())
519 return _call_hook('pre_push', extras, GitMessageWriter())
520
520
521
521
522 def git_post_receive(unused_repo_path, revision_lines, env):
522 def git_post_receive(unused_repo_path, revision_lines, env):
523 """
523 """
524 Post push hook.
524 Post push hook.
525
525
526 :param extras: dictionary containing the keys defined in simplevcs
526 :param extras: dictionary containing the keys defined in simplevcs
527 :type extras: dict
527 :type extras: dict
528
528
529 :return: status code of the hook. 0 for success.
529 :return: status code of the hook. 0 for success.
530 :rtype: int
530 :rtype: int
531 """
531 """
532 extras = json.loads(env['RC_SCM_DATA'])
532 extras = json.loads(env['RC_SCM_DATA'])
533 if 'push' not in extras['hooks']:
533 if 'push' not in extras['hooks']:
534 return 0
534 return 0
535
535
536 rev_data = _parse_git_ref_lines(revision_lines)
536 rev_data = _parse_git_ref_lines(revision_lines)
537
537
538 git_revs = []
538 git_revs = []
539
539
540 # N.B.(skreft): it is ok to just call git, as git before calling a
540 # N.B.(skreft): it is ok to just call git, as git before calling a
541 # subcommand sets the PATH environment variable so that it point to the
541 # subcommand sets the PATH environment variable so that it point to the
542 # correct version of the git executable.
542 # correct version of the git executable.
543 empty_commit_id = '0' * 40
543 empty_commit_id = '0' * 40
544 branches = []
544 branches = []
545 tags = []
545 tags = []
546 for push_ref in rev_data:
546 for push_ref in rev_data:
547 type_ = push_ref['type']
547 type_ = push_ref['type']
548
548
549 if type_ == 'heads':
549 if type_ == 'heads':
550 if push_ref['old_rev'] == empty_commit_id:
550 if push_ref['old_rev'] == empty_commit_id:
551 # starting new branch case
551 # starting new branch case
552 if push_ref['name'] not in branches:
552 if push_ref['name'] not in branches:
553 branches.append(push_ref['name'])
553 branches.append(push_ref['name'])
554
554
555 # Fix up head revision if needed
555 # Fix up head revision if needed
556 cmd = [settings.GIT_EXECUTABLE, 'show', 'HEAD']
556 cmd = [settings.GIT_EXECUTABLE, 'show', 'HEAD']
557 try:
557 try:
558 subprocessio.run_command(cmd, env=os.environ.copy())
558 subprocessio.run_command(cmd, env=os.environ.copy())
559 except Exception:
559 except Exception:
560 cmd = [settings.GIT_EXECUTABLE, 'symbolic-ref', 'HEAD',
560 cmd = [settings.GIT_EXECUTABLE, 'symbolic-ref', 'HEAD',
561 'refs/heads/%s' % push_ref['name']]
561 'refs/heads/%s' % push_ref['name']]
562 print("Setting default branch to %s" % push_ref['name'])
562 print("Setting default branch to %s" % push_ref['name'])
563 subprocessio.run_command(cmd, env=os.environ.copy())
563 subprocessio.run_command(cmd, env=os.environ.copy())
564
564
565 cmd = [settings.GIT_EXECUTABLE, 'for-each-ref',
565 cmd = [settings.GIT_EXECUTABLE, 'for-each-ref',
566 '--format=%(refname)', 'refs/heads/*']
566 '--format=%(refname)', 'refs/heads/*']
567 stdout, stderr = subprocessio.run_command(
567 stdout, stderr = subprocessio.run_command(
568 cmd, env=os.environ.copy())
568 cmd, env=os.environ.copy())
569 heads = stdout
569 heads = stdout
570 heads = heads.replace(push_ref['ref'], '')
570 heads = heads.replace(push_ref['ref'], '')
571 heads = ' '.join(head for head
571 heads = ' '.join(head for head
572 in heads.splitlines() if head) or '.'
572 in heads.splitlines() if head) or '.'
573 cmd = [settings.GIT_EXECUTABLE, 'log', '--reverse',
573 cmd = [settings.GIT_EXECUTABLE, 'log', '--reverse',
574 '--pretty=format:%H', '--', push_ref['new_rev'],
574 '--pretty=format:%H', '--', push_ref['new_rev'],
575 '--not', heads]
575 '--not', heads]
576 stdout, stderr = subprocessio.run_command(
576 stdout, stderr = subprocessio.run_command(
577 cmd, env=os.environ.copy())
577 cmd, env=os.environ.copy())
578 git_revs.extend(stdout.splitlines())
578 git_revs.extend(stdout.splitlines())
579 elif push_ref['new_rev'] == empty_commit_id:
579 elif push_ref['new_rev'] == empty_commit_id:
580 # delete branch case
580 # delete branch case
581 git_revs.append('delete_branch=>%s' % push_ref['name'])
581 git_revs.append('delete_branch=>%s' % push_ref['name'])
582 else:
582 else:
583 if push_ref['name'] not in branches:
583 if push_ref['name'] not in branches:
584 branches.append(push_ref['name'])
584 branches.append(push_ref['name'])
585
585
586 cmd = [settings.GIT_EXECUTABLE, 'log',
586 cmd = [settings.GIT_EXECUTABLE, 'log',
587 '{old_rev}..{new_rev}'.format(**push_ref),
587 '{old_rev}..{new_rev}'.format(**push_ref),
588 '--reverse', '--pretty=format:%H']
588 '--reverse', '--pretty=format:%H']
589 stdout, stderr = subprocessio.run_command(
589 stdout, stderr = subprocessio.run_command(
590 cmd, env=os.environ.copy())
590 cmd, env=os.environ.copy())
591 git_revs.extend(stdout.splitlines())
591 git_revs.extend(stdout.splitlines())
592 elif type_ == 'tags':
592 elif type_ == 'tags':
593 if push_ref['name'] not in tags:
593 if push_ref['name'] not in tags:
594 tags.append(push_ref['name'])
594 tags.append(push_ref['name'])
595 git_revs.append('tag=>%s' % push_ref['name'])
595 git_revs.append('tag=>%s' % push_ref['name'])
596
596
597 extras['hook_type'] = 'post_receive'
597 extras['hook_type'] = 'post_receive'
598 extras['commit_ids'] = git_revs
598 extras['commit_ids'] = git_revs
599 extras['new_refs'] = {
599 extras['new_refs'] = {
600 'branches': branches,
600 'branches': branches,
601 'bookmarks': [],
601 'bookmarks': [],
602 'tags': tags,
602 'tags': tags,
603 }
603 }
604
604
605 if 'repo_size' in extras['hooks']:
605 if 'repo_size' in extras['hooks']:
606 try:
606 try:
607 _call_hook('repo_size', extras, GitMessageWriter())
607 _call_hook('repo_size', extras, GitMessageWriter())
608 except:
608 except:
609 pass
609 pass
610
610
611 return _call_hook('post_push', extras, GitMessageWriter())
611 return _call_hook('post_push', extras, GitMessageWriter())
612
612
613
613
614 def _get_extras_from_txn_id(path, txn_id):
614 def _get_extras_from_txn_id(path, txn_id):
615 extras = {}
615 extras = {}
616 try:
616 try:
617 cmd = ['svnlook', 'pget',
617 cmd = ['svnlook', 'pget',
618 '-t', txn_id,
618 '-t', txn_id,
619 '--revprop', path, 'rc-scm-extras']
619 '--revprop', path, 'rc-scm-extras']
620 stdout, stderr = subprocessio.run_command(
620 stdout, stderr = subprocessio.run_command(
621 cmd, env=os.environ.copy())
621 cmd, env=os.environ.copy())
622 extras = json.loads(base64.urlsafe_b64decode(stdout))
622 extras = json.loads(base64.urlsafe_b64decode(stdout))
623 except Exception:
623 except Exception:
624 log.exception('Failed to extract extras info from txn_id')
624 log.exception('Failed to extract extras info from txn_id')
625
625
626 return extras
626 return extras
627
627
628
628
629 def _get_extras_from_commit_id(commit_id, path):
629 def _get_extras_from_commit_id(commit_id, path):
630 extras = {}
630 extras = {}
631 try:
631 try:
632 cmd = ['svnlook', 'pget',
632 cmd = ['svnlook', 'pget',
633 '-r', commit_id,
633 '-r', commit_id,
634 '--revprop', path, 'rc-scm-extras']
634 '--revprop', path, 'rc-scm-extras']
635 stdout, stderr = subprocessio.run_command(
635 stdout, stderr = subprocessio.run_command(
636 cmd, env=os.environ.copy())
636 cmd, env=os.environ.copy())
637 extras = json.loads(base64.urlsafe_b64decode(stdout))
637 extras = json.loads(base64.urlsafe_b64decode(stdout))
638 except Exception:
638 except Exception:
639 log.exception('Failed to extract extras info from commit_id')
639 log.exception('Failed to extract extras info from commit_id')
640
640
641 return extras
641 return extras
642
642
643
643
644 def svn_pre_commit(repo_path, commit_data, env):
644 def svn_pre_commit(repo_path, commit_data, env):
645 path, txn_id = commit_data
645 path, txn_id = commit_data
646 branches = []
646 branches = []
647 tags = []
647 tags = []
648
648
649 if env.get('RC_SCM_DATA'):
649 if env.get('RC_SCM_DATA'):
650 extras = json.loads(env['RC_SCM_DATA'])
650 extras = json.loads(env['RC_SCM_DATA'])
651 else:
651 else:
652 # fallback method to read from TXN-ID stored data
652 # fallback method to read from TXN-ID stored data
653 extras = _get_extras_from_txn_id(path, txn_id)
653 extras = _get_extras_from_txn_id(path, txn_id)
654 if not extras:
654 if not extras:
655 return 0
655 return 0
656
656
657 extras['hook_type'] = 'pre_commit'
657 extras['commit_ids'] = []
658 extras['commit_ids'] = []
658 extras['txn_id'] = txn_id
659 extras['txn_id'] = txn_id
659 extras['new_refs'] = {
660 extras['new_refs'] = {
660 'total_commits': 1,
661 'total_commits': 1,
661 'branches': branches,
662 'branches': branches,
662 'bookmarks': [],
663 'bookmarks': [],
663 'tags': tags,
664 'tags': tags,
664 }
665 }
665
666
666 return _call_hook('pre_push', extras, SvnMessageWriter())
667 return _call_hook('pre_push', extras, SvnMessageWriter())
667
668
668
669
669 def svn_post_commit(repo_path, commit_data, env):
670 def svn_post_commit(repo_path, commit_data, env):
670 """
671 """
671 commit_data is path, rev, txn_id
672 commit_data is path, rev, txn_id
672 """
673 """
673 path, commit_id, txn_id = commit_data
674 path, commit_id, txn_id = commit_data
674 branches = []
675 branches = []
675 tags = []
676 tags = []
676
677
677 if env.get('RC_SCM_DATA'):
678 if env.get('RC_SCM_DATA'):
678 extras = json.loads(env['RC_SCM_DATA'])
679 extras = json.loads(env['RC_SCM_DATA'])
679 else:
680 else:
680 # fallback method to read from TXN-ID stored data
681 # fallback method to read from TXN-ID stored data
681 extras = _get_extras_from_commit_id(commit_id, path)
682 extras = _get_extras_from_commit_id(commit_id, path)
682 if not extras:
683 if not extras:
683 return 0
684 return 0
684
685
686 extras['hook_type'] = 'post_commit'
685 extras['commit_ids'] = [commit_id]
687 extras['commit_ids'] = [commit_id]
686 extras['txn_id'] = txn_id
688 extras['txn_id'] = txn_id
687 extras['new_refs'] = {
689 extras['new_refs'] = {
688 'branches': branches,
690 'branches': branches,
689 'bookmarks': [],
691 'bookmarks': [],
690 'tags': tags,
692 'tags': tags,
691 'total_commits': 1,
693 'total_commits': 1,
692 }
694 }
693
695
694 if 'repo_size' in extras['hooks']:
696 if 'repo_size' in extras['hooks']:
695 try:
697 try:
696 _call_hook('repo_size', extras, SvnMessageWriter())
698 _call_hook('repo_size', extras, SvnMessageWriter())
697 except Exception:
699 except Exception:
698 pass
700 pass
699
701
700 return _call_hook('post_push', extras, SvnMessageWriter())
702 return _call_hook('post_push', extras, SvnMessageWriter())
General Comments 0
You need to be logged in to leave comments. Login now