##// END OF EJS Templates
Fixed githooks for fetching multiple tags and branches....
marcink -
r2617:c0ec29b2 beta
parent child Browse files
Show More
@@ -1,29 +1,31 b''
1 1 #!/usr/bin/env python
2 2 import os
3 3 import sys
4 4
5 5 try:
6 6 import rhodecode
7 RC_HOOK_VER = '_TMPL_'
8 os.environ['RC_HOOK_VER'] = RC_HOOK_VER
7 9 from rhodecode.lib.hooks import handle_git_post_receive
8 10 except ImportError:
9 11 rhodecode = None
10 12
11 13
12 14 def main():
13 15 if rhodecode is None:
14 16 # exit with success if we cannot import rhodecode !!
15 17 # this allows simply push to this repo even without
16 18 # rhodecode
17 19 sys.exit(0)
18 20
19 21 repo_path = os.path.abspath('.')
20 push_data = sys.stdin.read().strip().split(' ')
22 push_data = sys.stdin.readlines()
21 23 # os.environ is modified here by a subprocess call that
22 24 # runs git and later git executes this hook.
23 25 # Environ get's some additional info from rhodecode system
24 26 # like IP or username from basic-auth
25 27 handle_git_post_receive(repo_path, push_data, os.environ)
26 28 sys.exit(0)
27 29
28 30 if __name__ == '__main__':
29 31 main()
@@ -1,259 +1,278 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.hooks
4 4 ~~~~~~~~~~~~~~~~~~~
5 5
6 6 Hooks runned by rhodecode
7 7
8 8 :created_on: Aug 6, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25 import os
26 26 import sys
27 27 import binascii
28 28 from inspect import isfunction
29 29
30 30 from mercurial.scmutil import revrange
31 31 from mercurial.node import nullrev
32 32
33 33 from rhodecode.lib import helpers as h
34 34 from rhodecode.lib.utils import action_logger
35 35 from rhodecode.lib.vcs.backends.base import EmptyChangeset
36 36
37 37
38 38 def _get_scm_size(alias, root_path):
39 39
40 40 if not alias.startswith('.'):
41 41 alias += '.'
42 42
43 43 size_scm, size_root = 0, 0
44 44 for path, dirs, files in os.walk(root_path):
45 45 if path.find(alias) != -1:
46 46 for f in files:
47 47 try:
48 48 size_scm += os.path.getsize(os.path.join(path, f))
49 49 except OSError:
50 50 pass
51 51 else:
52 52 for f in files:
53 53 try:
54 54 size_root += os.path.getsize(os.path.join(path, f))
55 55 except OSError:
56 56 pass
57 57
58 58 size_scm_f = h.format_byte_size(size_scm)
59 59 size_root_f = h.format_byte_size(size_root)
60 60 size_total_f = h.format_byte_size(size_root + size_scm)
61 61
62 62 return size_scm_f, size_root_f, size_total_f
63 63
64 64
65 65 def repo_size(ui, repo, hooktype=None, **kwargs):
66 66 """
67 67 Presents size of repository after push
68 68
69 69 :param ui:
70 70 :param repo:
71 71 :param hooktype:
72 72 """
73 73
74 74 size_hg_f, size_root_f, size_total_f = _get_scm_size('.hg', repo.root)
75 75
76 76 last_cs = repo[len(repo) - 1]
77 77
78 78 msg = ('Repository size .hg:%s repo:%s total:%s\n'
79 79 'Last revision is now r%s:%s\n') % (
80 80 size_hg_f, size_root_f, size_total_f, last_cs.rev(), last_cs.hex()[:12]
81 81 )
82 82
83 83 sys.stdout.write(msg)
84 84
85 85
86 86 def log_pull_action(ui, repo, **kwargs):
87 87 """
88 88 Logs user last pull action
89 89
90 90 :param ui:
91 91 :param repo:
92 92 """
93 93 extras = dict(repo.ui.configitems('rhodecode_extras'))
94 94 username = extras['username']
95 95 repository = extras['repository']
96 96 scm = extras['scm']
97 97 action = 'pull'
98 98
99 99 action_logger(username, action, repository, extras['ip'], commit=True)
100 100 # extension hook call
101 101 from rhodecode import EXTENSIONS
102 102 callback = getattr(EXTENSIONS, 'PULL_HOOK', None)
103 103
104 104 if isfunction(callback):
105 105 kw = {}
106 106 kw.update(extras)
107 107 callback(**kw)
108 108 return 0
109 109
110 110
111 111 def log_push_action(ui, repo, **kwargs):
112 112 """
113 113 Maps user last push action to new changeset id, from mercurial
114 114
115 115 :param ui:
116 116 :param repo: repo object containing the `ui` object
117 117 """
118 118
119 119 extras = dict(repo.ui.configitems('rhodecode_extras'))
120 120 username = extras['username']
121 121 repository = extras['repository']
122 122 action = extras['action'] + ':%s'
123 123 scm = extras['scm']
124 124
125 125 if scm == 'hg':
126 126 node = kwargs['node']
127 127
128 128 def get_revs(repo, rev_opt):
129 129 if rev_opt:
130 130 revs = revrange(repo, rev_opt)
131 131
132 132 if len(revs) == 0:
133 133 return (nullrev, nullrev)
134 134 return (max(revs), min(revs))
135 135 else:
136 136 return (len(repo) - 1, 0)
137 137
138 138 stop, start = get_revs(repo, [node + ':'])
139 139 h = binascii.hexlify
140 140 revs = [h(repo[r].node()) for r in xrange(start, stop + 1)]
141 141 elif scm == 'git':
142 142 revs = kwargs.get('_git_revs', [])
143 143 if '_git_revs' in kwargs:
144 144 kwargs.pop('_git_revs')
145 145
146 146 action = action % ','.join(revs)
147 147
148 148 action_logger(username, action, repository, extras['ip'], commit=True)
149 149
150 150 # extension hook call
151 151 from rhodecode import EXTENSIONS
152 152 callback = getattr(EXTENSIONS, 'PUSH_HOOK', None)
153 153 if isfunction(callback):
154 154 kw = {'pushed_revs': revs}
155 155 kw.update(extras)
156 156 callback(**kw)
157 157 return 0
158 158
159 159
160 160 def log_create_repository(repository_dict, created_by, **kwargs):
161 161 """
162 162 Post create repository Hook. This is a dummy function for admins to re-use
163 163 if needed. It's taken from rhodecode-extensions module and executed
164 164 if present
165 165
166 166 :param repository: dict dump of repository object
167 167 :param created_by: username who created repository
168 168 :param created_date: date of creation
169 169
170 170 available keys of repository_dict:
171 171
172 172 'repo_type',
173 173 'description',
174 174 'private',
175 175 'created_on',
176 176 'enable_downloads',
177 177 'repo_id',
178 178 'user_id',
179 179 'enable_statistics',
180 180 'clone_uri',
181 181 'fork_id',
182 182 'group_id',
183 183 'repo_name'
184 184
185 185 """
186 186 from rhodecode import EXTENSIONS
187 187 callback = getattr(EXTENSIONS, 'CREATE_REPO_HOOK', None)
188 188 if isfunction(callback):
189 189 kw = {}
190 190 kw.update(repository_dict)
191 191 kw.update({'created_by': created_by})
192 192 kw.update(kwargs)
193 193 return callback(**kw)
194 194
195 195 return 0
196 196
197 197
198 198 def handle_git_post_receive(repo_path, revs, env):
199 199 """
200 200 A really hacky method that is runned by git post-receive hook and logs
201 201 an push action together with pushed revisions. It's executed by subprocess
202 202 thus needs all info to be able to create a on the fly pylons enviroment,
203 203 connect to database and run the logging code. Hacky as sh*t but works.
204 204
205 205 :param repo_path:
206 206 :type repo_path:
207 207 :param revs:
208 208 :type revs:
209 209 :param env:
210 210 :type env:
211 211 """
212 212 from paste.deploy import appconfig
213 213 from sqlalchemy import engine_from_config
214 214 from rhodecode.config.environment import load_environment
215 215 from rhodecode.model import init_model
216 216 from rhodecode.model.db import RhodeCodeUi
217 217 from rhodecode.lib.utils import make_ui
218 218 from rhodecode.model.db import Repository
219 219
220 220 path, ini_name = os.path.split(env['RHODECODE_CONFIG_FILE'])
221 221 conf = appconfig('config:%s' % ini_name, relative_to=path)
222 222 load_environment(conf.global_conf, conf.local_conf)
223 223
224 224 engine = engine_from_config(conf, 'sqlalchemy.db1.')
225 225 init_model(engine)
226 226
227 227 baseui = make_ui('db')
228 # fix if it's not a bare repo
229 if repo_path.endswith('.git'):
230 repo_path = repo_path[:-4]
228 231 repo = Repository.get_by_full_path(repo_path)
229
230 232 _hooks = dict(baseui.configitems('hooks')) or {}
231 233 # if push hook is enabled via web interface
232 if _hooks.get(RhodeCodeUi.HOOK_PUSH):
234 if repo and _hooks.get(RhodeCodeUi.HOOK_PUSH):
233 235
234 236 extras = {
235 237 'username': env['RHODECODE_USER'],
236 238 'repository': repo.repo_name,
237 239 'scm': 'git',
238 240 'action': 'push',
239 241 'ip': env['RHODECODE_CONFIG_IP'],
240 242 }
241 243 for k, v in extras.items():
242 244 baseui.setconfig('rhodecode_extras', k, v)
243 245 repo = repo.scm_instance
244 246 repo.ui = baseui
245 old_rev, new_rev, ref = revs
246 if old_rev == EmptyChangeset().raw_id:
247 cmd = "for-each-ref --format='%(refname)' 'refs/heads/*'"
248 heads = repo.run_git_command(cmd)[0]
249 heads = heads.replace(ref, '')
250 heads = ' '.join(map(lambda c: c.strip('\n').strip(),
251 heads.splitlines()))
252 cmd = ('log ' + new_rev +
253 ' --reverse --pretty=format:"%H" --not ' + heads)
254 else:
255 cmd = ('log ' + old_rev + '..' + new_rev +
256 ' --reverse --pretty=format:"%H"')
257 git_revs = repo.run_git_command(cmd)[0].splitlines()
247
248 rev_data = []
249 for l in revs:
250 old_rev, new_rev, ref = l.split(' ')
251 _ref_data = ref.split('/')
252 if _ref_data[1] in ['tags', 'heads']:
253 rev_data.append({'old_rev': old_rev,
254 'new_rev': new_rev,
255 'ref': ref,
256 'type': _ref_data[1],
257 'name': _ref_data[2].strip()})
258
259 git_revs = []
260 for push_ref in rev_data:
261 _type = push_ref['type']
262 if _type == 'heads':
263 if push_ref['old_rev'] == EmptyChangeset().raw_id:
264 cmd = "for-each-ref --format='%(refname)' 'refs/heads/*'"
265 heads = repo.run_git_command(cmd)[0]
266 heads = heads.replace(push_ref['ref'], '')
267 heads = ' '.join(map(lambda c: c.strip('\n').strip(),
268 heads.splitlines()))
269 cmd = (('log %(new_rev)s' % push_ref) +
270 ' --reverse --pretty=format:"%H" --not ' + heads)
271 else:
272 cmd = (('log %(old_rev)s..%(new_rev)s' % push_ref) +
273 ' --reverse --pretty=format:"%H"')
274 git_revs += repo.run_git_command(cmd)[0].splitlines()
275 elif _type == 'tags':
276 git_revs += [push_ref['name']]
258 277
259 278 log_push_action(baseui, repo, _git_revs=git_revs)
General Comments 0
You need to be logged in to leave comments. Login now