##// END OF EJS Templates
fixed possible unicode errors on repo get function
marcink -
r2672:16980771 beta
parent child Browse files
Show More
@@ -1,138 +1,139
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.__init__
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 The application's model objects
7 7
8 8 :created_on: Nov 25, 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
14 14 :example:
15 15
16 16 .. code-block:: python
17 17
18 18 from paste.deploy import appconfig
19 19 from pylons import config
20 20 from sqlalchemy import engine_from_config
21 21 from rhodecode.config.environment import load_environment
22 22
23 23 conf = appconfig('config:development.ini', relative_to = './../../')
24 24 load_environment(conf.global_conf, conf.local_conf)
25 25
26 26 engine = engine_from_config(config, 'sqlalchemy.')
27 27 init_model(engine)
28 28 # RUN YOUR CODE HERE
29 29
30 30 """
31 31 # This program is free software: you can redistribute it and/or modify
32 32 # it under the terms of the GNU General Public License as published by
33 33 # the Free Software Foundation, either version 3 of the License, or
34 34 # (at your option) any later version.
35 35 #
36 36 # This program is distributed in the hope that it will be useful,
37 37 # but WITHOUT ANY WARRANTY; without even the implied warranty of
38 38 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 39 # GNU General Public License for more details.
40 40 #
41 41 # You should have received a copy of the GNU General Public License
42 42 # along with this program. If not, see <http://www.gnu.org/licenses/>.
43 43
44 44 import logging
45 45 from rhodecode.model import meta
46 from rhodecode.lib.utils2 import safe_str
46 47
47 48 log = logging.getLogger(__name__)
48 49
49 50
50 51 def init_model(engine):
51 52 """
52 53 Initializes db session, bind the engine with the metadata,
53 54 Call this before using any of the tables or classes in the model,
54 55 preferably once in application start
55 56
56 57 :param engine: engine to bind to
57 58 """
58 59 log.info("initializing db for %s" % engine)
59 60 meta.Base.metadata.bind = engine
60 61
61 62
62 63 class BaseModel(object):
63 64 """
64 65 Base Model for all RhodeCode models, it adds sql alchemy session
65 66 into instance of model
66 67
67 68 :param sa: If passed it reuses this session instead of creating a new one
68 69 """
69 70
70 71 cls = None # override in child class
71 72
72 73 def __init__(self, sa=None):
73 74 if sa is not None:
74 75 self.sa = sa
75 76 else:
76 77 self.sa = meta.Session()
77 78
78 79 def _get_instance(self, cls, instance, callback=None):
79 80 """
80 81 Get's instance of given cls using some simple lookup mechanism.
81 82
82 83 :param cls: class to fetch
83 84 :param instance: int or Instance
84 85 :param callback: callback to call if all lookups failed
85 86 """
86 87
87 88 if isinstance(instance, cls):
88 89 return instance
89 elif isinstance(instance, (int, long)) or str(instance).isdigit():
90 elif isinstance(instance, (int, long)) or safe_str(instance).isdigit():
90 91 return cls.get(instance)
91 92 else:
92 93 if instance:
93 94 if callback is None:
94 95 raise Exception(
95 96 'given object must be int, long or Instance of %s '
96 97 'got %s, no callback provided' % (cls, type(instance))
97 98 )
98 99 else:
99 100 return callback(instance)
100 101
101 102 def _get_user(self, user):
102 103 """
103 104 Helper method to get user by ID, or username fallback
104 105
105 106 :param user:
106 107 :type user: UserID, username, or User instance
107 108 """
108 109 from rhodecode.model.db import User
109 110 return self._get_instance(User, user,
110 111 callback=User.get_by_username)
111 112
112 113 def _get_repo(self, repository):
113 114 """
114 115 Helper method to get repository by ID, or repository name
115 116
116 117 :param repository:
117 118 :type repository: RepoID, repository name or Repository Instance
118 119 """
119 120 from rhodecode.model.db import Repository
120 121 return self._get_instance(Repository, repository,
121 122 callback=Repository.get_by_repo_name)
122 123
123 124 def _get_perm(self, permission):
124 125 """
125 126 Helper method to get permission by ID, or permission name
126 127
127 128 :param permission:
128 129 :type permission: PermissionID, permission_name or Permission instance
129 130 """
130 131 from rhodecode.model.db import Permission
131 132 return self._get_instance(Permission, permission,
132 133 callback=Permission.get_by_key)
133 134
134 135 def get_all(self):
135 136 """
136 137 Returns all instances of what is defined in `cls` class variable
137 138 """
138 139 return self.cls.getAll()
@@ -1,595 +1,595
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.scm
4 4 ~~~~~~~~~~~~~~~~~~~
5 5
6 6 Scm model for RhodeCode
7 7
8 8 :created_on: Apr 9, 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 from __future__ import with_statement
26 26 import os
27 27 import re
28 28 import time
29 29 import traceback
30 30 import logging
31 31 import cStringIO
32 32 import pkg_resources
33 33 from os.path import dirname as dn, join as jn
34 34
35 35 from sqlalchemy import func
36 36 from pylons.i18n.translation import _
37 37
38 38 import rhodecode
39 39 from rhodecode.lib.vcs import get_backend
40 40 from rhodecode.lib.vcs.exceptions import RepositoryError
41 41 from rhodecode.lib.vcs.utils.lazy import LazyProperty
42 42 from rhodecode.lib.vcs.nodes import FileNode
43 43
44 44 from rhodecode import BACKENDS
45 45 from rhodecode.lib import helpers as h
46 46 from rhodecode.lib.utils2 import safe_str, safe_unicode
47 47 from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny
48 48 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
49 49 action_logger, EmptyChangeset, REMOVED_REPO_PAT
50 50 from rhodecode.model import BaseModel
51 51 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
52 52 UserFollowing, UserLog, User, RepoGroup, PullRequest
53 53
54 54 log = logging.getLogger(__name__)
55 55
56 56
57 57 class UserTemp(object):
58 58 def __init__(self, user_id):
59 59 self.user_id = user_id
60 60
61 61 def __repr__(self):
62 62 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
63 63
64 64
65 65 class RepoTemp(object):
66 66 def __init__(self, repo_id):
67 67 self.repo_id = repo_id
68 68
69 69 def __repr__(self):
70 70 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
71 71
72 72
73 73 class CachedRepoList(object):
74 74 """
75 75 Cached repo list, uses in-memory cache after initialization, that is
76 76 super fast
77 77 """
78 78
79 79 def __init__(self, db_repo_list, repos_path, order_by=None):
80 80 self.db_repo_list = db_repo_list
81 81 self.repos_path = repos_path
82 82 self.order_by = order_by
83 83 self.reversed = (order_by or '').startswith('-')
84 84
85 85 def __len__(self):
86 86 return len(self.db_repo_list)
87 87
88 88 def __repr__(self):
89 89 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
90 90
91 91 def __iter__(self):
92 92 # pre-propagated cache_map to save executing select statements
93 93 # for each repo
94 94 cache_map = CacheInvalidation.get_cache_map()
95 95
96 96 for dbr in self.db_repo_list:
97 97 scmr = dbr.scm_instance_cached(cache_map)
98 98 # check permission at this level
99 99 if not HasRepoPermissionAny(
100 100 'repository.read', 'repository.write', 'repository.admin'
101 101 )(dbr.repo_name, 'get repo check'):
102 102 continue
103 103
104 104 if scmr is None:
105 105 log.error(
106 106 '%s this repository is present in database but it '
107 107 'cannot be created as an scm instance' % dbr.repo_name
108 108 )
109 109 continue
110 110
111 111 last_change = scmr.last_change
112 112 tip = h.get_changeset_safe(scmr, 'tip')
113 113
114 114 tmp_d = {}
115 115 tmp_d['name'] = dbr.repo_name
116 116 tmp_d['name_sort'] = tmp_d['name'].lower()
117 117 tmp_d['description'] = dbr.description
118 118 tmp_d['description_sort'] = tmp_d['description'].lower()
119 119 tmp_d['last_change'] = last_change
120 120 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
121 121 tmp_d['tip'] = tip.raw_id
122 122 tmp_d['tip_sort'] = tip.revision
123 123 tmp_d['rev'] = tip.revision
124 124 tmp_d['contact'] = dbr.user.full_contact
125 125 tmp_d['contact_sort'] = tmp_d['contact']
126 126 tmp_d['owner_sort'] = tmp_d['contact']
127 127 tmp_d['repo_archives'] = list(scmr._get_archives())
128 128 tmp_d['last_msg'] = tip.message
129 129 tmp_d['author'] = tip.author
130 130 tmp_d['dbrepo'] = dbr.get_dict()
131 131 tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork else {}
132 132 yield tmp_d
133 133
134 134
135 135 class SimpleCachedRepoList(CachedRepoList):
136 136 """
137 137 Lighter version of CachedRepoList without the scm initialisation
138 138 """
139 139
140 140 def __iter__(self):
141 141 for dbr in self.db_repo_list:
142 142 # check permission at this level
143 143 if not HasRepoPermissionAny(
144 144 'repository.read', 'repository.write', 'repository.admin'
145 145 )(dbr.repo_name, 'get repo check'):
146 146 continue
147 147
148 148 tmp_d = {}
149 149 tmp_d['name'] = dbr.repo_name
150 150 tmp_d['name_sort'] = tmp_d['name'].lower()
151 151 tmp_d['description'] = dbr.description
152 152 tmp_d['description_sort'] = tmp_d['description'].lower()
153 153 tmp_d['dbrepo'] = dbr.get_dict()
154 154 tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork else {}
155 155 yield tmp_d
156 156
157 157
158 158 class GroupList(object):
159 159
160 160 def __init__(self, db_repo_group_list):
161 161 self.db_repo_group_list = db_repo_group_list
162 162
163 163 def __len__(self):
164 164 return len(self.db_repo_group_list)
165 165
166 166 def __repr__(self):
167 167 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
168 168
169 169 def __iter__(self):
170 170 for dbgr in self.db_repo_group_list:
171 171 # check permission at this level
172 172 if not HasReposGroupPermissionAny(
173 173 'group.read', 'group.write', 'group.admin'
174 174 )(dbgr.group_name, 'get group repo check'):
175 175 continue
176 176
177 177 yield dbgr
178 178
179 179
180 180 class ScmModel(BaseModel):
181 181 """
182 182 Generic Scm Model
183 183 """
184 184
185 185 def __get_repo(self, instance):
186 186 cls = Repository
187 187 if isinstance(instance, cls):
188 188 return instance
189 elif isinstance(instance, int) or str(instance).isdigit():
189 elif isinstance(instance, int) or safe_str(instance).isdigit():
190 190 return cls.get(instance)
191 191 elif isinstance(instance, basestring):
192 192 return cls.get_by_repo_name(instance)
193 193 elif instance:
194 194 raise Exception('given object must be int, basestr or Instance'
195 195 ' of %s got %s' % (type(cls), type(instance)))
196 196
197 197 @LazyProperty
198 198 def repos_path(self):
199 199 """
200 200 Get's the repositories root path from database
201 201 """
202 202
203 203 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
204 204
205 205 return q.ui_value
206 206
207 207 def repo_scan(self, repos_path=None):
208 208 """
209 209 Listing of repositories in given path. This path should not be a
210 210 repository itself. Return a dictionary of repository objects
211 211
212 212 :param repos_path: path to directory containing repositories
213 213 """
214 214
215 215 if repos_path is None:
216 216 repos_path = self.repos_path
217 217
218 218 log.info('scanning for repositories in %s' % repos_path)
219 219
220 220 baseui = make_ui('db')
221 221 repos = {}
222 222
223 223 for name, path in get_filesystem_repos(repos_path, recursive=True):
224 224 # skip removed repos
225 225 if REMOVED_REPO_PAT.match(name):
226 226 continue
227 227
228 228 # name need to be decomposed and put back together using the /
229 229 # since this is internal storage separator for rhodecode
230 230 name = Repository.url_sep().join(name.split(os.sep))
231 231
232 232 try:
233 233 if name in repos:
234 234 raise RepositoryError('Duplicate repository name %s '
235 235 'found in %s' % (name, path))
236 236 else:
237 237
238 238 klass = get_backend(path[0])
239 239
240 240 if path[0] == 'hg' and path[0] in BACKENDS.keys():
241 241 repos[name] = klass(safe_str(path[1]), baseui=baseui)
242 242
243 243 if path[0] == 'git' and path[0] in BACKENDS.keys():
244 244 repos[name] = klass(path[1])
245 245 except OSError:
246 246 continue
247 247
248 248 return repos
249 249
250 250 def get_repos(self, all_repos=None, sort_key=None, simple=False):
251 251 """
252 252 Get all repos from db and for each repo create it's
253 253 backend instance and fill that backed with information from database
254 254
255 255 :param all_repos: list of repository names as strings
256 256 give specific repositories list, good for filtering
257 257
258 258 :param sort_key: initial sorting of repos
259 259 :param simple: use SimpleCachedList - one without the SCM info
260 260 """
261 261 if all_repos is None:
262 262 all_repos = self.sa.query(Repository)\
263 263 .filter(Repository.group_id == None)\
264 264 .order_by(func.lower(Repository.repo_name)).all()
265 265 if simple:
266 266 repo_iter = SimpleCachedRepoList(all_repos,
267 267 repos_path=self.repos_path,
268 268 order_by=sort_key)
269 269 else:
270 270 repo_iter = CachedRepoList(all_repos,
271 271 repos_path=self.repos_path,
272 272 order_by=sort_key)
273 273
274 274 return repo_iter
275 275
276 276 def get_repos_groups(self, all_groups=None):
277 277 if all_groups is None:
278 278 all_groups = RepoGroup.query()\
279 279 .filter(RepoGroup.group_parent_id == None).all()
280 280 group_iter = GroupList(all_groups)
281 281
282 282 return group_iter
283 283
284 284 def mark_for_invalidation(self, repo_name):
285 285 """
286 286 Puts cache invalidation task into db for
287 287 further global cache invalidation
288 288
289 289 :param repo_name: this repo that should invalidation take place
290 290 """
291 291 CacheInvalidation.set_invalidate(repo_name)
292 292
293 293 def toggle_following_repo(self, follow_repo_id, user_id):
294 294
295 295 f = self.sa.query(UserFollowing)\
296 296 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
297 297 .filter(UserFollowing.user_id == user_id).scalar()
298 298
299 299 if f is not None:
300 300 try:
301 301 self.sa.delete(f)
302 302 action_logger(UserTemp(user_id),
303 303 'stopped_following_repo',
304 304 RepoTemp(follow_repo_id))
305 305 return
306 306 except:
307 307 log.error(traceback.format_exc())
308 308 raise
309 309
310 310 try:
311 311 f = UserFollowing()
312 312 f.user_id = user_id
313 313 f.follows_repo_id = follow_repo_id
314 314 self.sa.add(f)
315 315
316 316 action_logger(UserTemp(user_id),
317 317 'started_following_repo',
318 318 RepoTemp(follow_repo_id))
319 319 except:
320 320 log.error(traceback.format_exc())
321 321 raise
322 322
323 323 def toggle_following_user(self, follow_user_id, user_id):
324 324 f = self.sa.query(UserFollowing)\
325 325 .filter(UserFollowing.follows_user_id == follow_user_id)\
326 326 .filter(UserFollowing.user_id == user_id).scalar()
327 327
328 328 if f is not None:
329 329 try:
330 330 self.sa.delete(f)
331 331 return
332 332 except:
333 333 log.error(traceback.format_exc())
334 334 raise
335 335
336 336 try:
337 337 f = UserFollowing()
338 338 f.user_id = user_id
339 339 f.follows_user_id = follow_user_id
340 340 self.sa.add(f)
341 341 except:
342 342 log.error(traceback.format_exc())
343 343 raise
344 344
345 345 def is_following_repo(self, repo_name, user_id, cache=False):
346 346 r = self.sa.query(Repository)\
347 347 .filter(Repository.repo_name == repo_name).scalar()
348 348
349 349 f = self.sa.query(UserFollowing)\
350 350 .filter(UserFollowing.follows_repository == r)\
351 351 .filter(UserFollowing.user_id == user_id).scalar()
352 352
353 353 return f is not None
354 354
355 355 def is_following_user(self, username, user_id, cache=False):
356 356 u = User.get_by_username(username)
357 357
358 358 f = self.sa.query(UserFollowing)\
359 359 .filter(UserFollowing.follows_user == u)\
360 360 .filter(UserFollowing.user_id == user_id).scalar()
361 361
362 362 return f is not None
363 363
364 364 def get_followers(self, repo):
365 365 repo = self._get_repo(repo)
366 366
367 367 return self.sa.query(UserFollowing)\
368 368 .filter(UserFollowing.follows_repository == repo).count()
369 369
370 370 def get_forks(self, repo):
371 371 repo = self._get_repo(repo)
372 372 return self.sa.query(Repository)\
373 373 .filter(Repository.fork == repo).count()
374 374
375 375 def get_pull_requests(self, repo):
376 376 repo = self._get_repo(repo)
377 377 return self.sa.query(PullRequest)\
378 378 .filter(PullRequest.other_repo == repo).count()
379 379
380 380 def mark_as_fork(self, repo, fork, user):
381 381 repo = self.__get_repo(repo)
382 382 fork = self.__get_repo(fork)
383 383 if fork and repo.repo_id == fork.repo_id:
384 384 raise Exception("Cannot set repository as fork of itself")
385 385 repo.fork = fork
386 386 self.sa.add(repo)
387 387 return repo
388 388
389 389 def pull_changes(self, repo, username):
390 390 dbrepo = self.__get_repo(repo)
391 391 clone_uri = dbrepo.clone_uri
392 392 if not clone_uri:
393 393 raise Exception("This repository doesn't have a clone uri")
394 394
395 395 repo = dbrepo.scm_instance
396 396 try:
397 397 extras = {
398 398 'ip': '',
399 399 'username': username,
400 400 'action': 'push_remote',
401 401 'repository': dbrepo.repo_name,
402 402 'scm': repo.alias,
403 403 }
404 404 Repository.inject_ui(repo, extras=extras)
405 405
406 406 if repo.alias == 'git':
407 407 repo.fetch(clone_uri)
408 408 else:
409 409 repo.pull(clone_uri)
410 410 self.mark_for_invalidation(dbrepo.repo_name)
411 411 except:
412 412 log.error(traceback.format_exc())
413 413 raise
414 414
415 415 def commit_change(self, repo, repo_name, cs, user, author, message,
416 416 content, f_path):
417 417
418 418 if repo.alias == 'hg':
419 419 from rhodecode.lib.vcs.backends.hg import \
420 420 MercurialInMemoryChangeset as IMC
421 421 elif repo.alias == 'git':
422 422 from rhodecode.lib.vcs.backends.git import \
423 423 GitInMemoryChangeset as IMC
424 424
425 425 # decoding here will force that we have proper encoded values
426 426 # in any other case this will throw exceptions and deny commit
427 427 content = safe_str(content)
428 428 path = safe_str(f_path)
429 429 # message and author needs to be unicode
430 430 # proper backend should then translate that into required type
431 431 message = safe_unicode(message)
432 432 author = safe_unicode(author)
433 433 m = IMC(repo)
434 434 m.change(FileNode(path, content))
435 435 tip = m.commit(message=message,
436 436 author=author,
437 437 parents=[cs], branch=cs.branch)
438 438
439 439 action = 'push_local:%s' % tip.raw_id
440 440 action_logger(user, action, repo_name)
441 441 self.mark_for_invalidation(repo_name)
442 442
443 443 def create_node(self, repo, repo_name, cs, user, author, message, content,
444 444 f_path):
445 445 if repo.alias == 'hg':
446 446 from rhodecode.lib.vcs.backends.hg import MercurialInMemoryChangeset as IMC
447 447 elif repo.alias == 'git':
448 448 from rhodecode.lib.vcs.backends.git import GitInMemoryChangeset as IMC
449 449 # decoding here will force that we have proper encoded values
450 450 # in any other case this will throw exceptions and deny commit
451 451
452 452 if isinstance(content, (basestring,)):
453 453 content = safe_str(content)
454 454 elif isinstance(content, (file, cStringIO.OutputType,)):
455 455 content = content.read()
456 456 else:
457 457 raise Exception('Content is of unrecognized type %s' % (
458 458 type(content)
459 459 ))
460 460
461 461 message = safe_unicode(message)
462 462 author = safe_unicode(author)
463 463 path = safe_str(f_path)
464 464 m = IMC(repo)
465 465
466 466 if isinstance(cs, EmptyChangeset):
467 467 # EmptyChangeset means we we're editing empty repository
468 468 parents = None
469 469 else:
470 470 parents = [cs]
471 471
472 472 m.add(FileNode(path, content=content))
473 473 tip = m.commit(message=message,
474 474 author=author,
475 475 parents=parents, branch=cs.branch)
476 476
477 477 action = 'push_local:%s' % tip.raw_id
478 478 action_logger(user, action, repo_name)
479 479 self.mark_for_invalidation(repo_name)
480 480
481 481 def get_nodes(self, repo_name, revision, root_path='/', flat=True):
482 482 """
483 483 recursive walk in root dir and return a set of all path in that dir
484 484 based on repository walk function
485 485
486 486 :param repo_name: name of repository
487 487 :param revision: revision for which to list nodes
488 488 :param root_path: root path to list
489 489 :param flat: return as a list, if False returns a dict with decription
490 490
491 491 """
492 492 _files = list()
493 493 _dirs = list()
494 494 try:
495 495 _repo = self.__get_repo(repo_name)
496 496 changeset = _repo.scm_instance.get_changeset(revision)
497 497 root_path = root_path.lstrip('/')
498 498 for topnode, dirs, files in changeset.walk(root_path):
499 499 for f in files:
500 500 _files.append(f.path if flat else {"name": f.path,
501 501 "type": "file"})
502 502 for d in dirs:
503 503 _dirs.append(d.path if flat else {"name": d.path,
504 504 "type": "dir"})
505 505 except RepositoryError:
506 506 log.debug(traceback.format_exc())
507 507 raise
508 508
509 509 return _dirs, _files
510 510
511 511 def get_unread_journal(self):
512 512 return self.sa.query(UserLog).count()
513 513
514 514 def get_repo_landing_revs(self, repo=None):
515 515 """
516 516 Generates select option with tags branches and bookmarks (for hg only)
517 517 grouped by type
518 518
519 519 :param repo:
520 520 :type repo:
521 521 """
522 522
523 523 hist_l = []
524 524 choices = []
525 525 repo = self.__get_repo(repo)
526 526 hist_l.append(['tip', _('latest tip')])
527 527 choices.append('tip')
528 528 if not repo:
529 529 return choices, hist_l
530 530
531 531 repo = repo.scm_instance
532 532
533 533 branches_group = ([(k, k) for k, v in
534 534 repo.branches.iteritems()], _("Branches"))
535 535 hist_l.append(branches_group)
536 536 choices.extend([x[0] for x in branches_group[0]])
537 537
538 538 if repo.alias == 'hg':
539 539 bookmarks_group = ([(k, k) for k, v in
540 540 repo.bookmarks.iteritems()], _("Bookmarks"))
541 541 hist_l.append(bookmarks_group)
542 542 choices.extend([x[0] for x in bookmarks_group[0]])
543 543
544 544 tags_group = ([(k, k) for k, v in
545 545 repo.tags.iteritems()], _("Tags"))
546 546 hist_l.append(tags_group)
547 547 choices.extend([x[0] for x in tags_group[0]])
548 548
549 549 return choices, hist_l
550 550
551 551 def install_git_hook(self, repo, force_create=False):
552 552 """
553 553 Creates a rhodecode hook inside a git repository
554 554
555 555 :param repo: Instance of VCS repo
556 556 :param force_create: Create even if same name hook exists
557 557 """
558 558
559 559 loc = jn(repo.path, 'hooks')
560 560 if not repo.bare:
561 561 loc = jn(repo.path, '.git', 'hooks')
562 562 if not os.path.isdir(loc):
563 563 os.makedirs(loc)
564 564
565 565 tmpl = pkg_resources.resource_string(
566 566 'rhodecode', jn('config', 'post_receive_tmpl.py')
567 567 )
568 568
569 569 _hook_file = jn(loc, 'post-receive')
570 570 _rhodecode_hook = False
571 571 log.debug('Installing git hook in repo %s' % repo)
572 572 if os.path.exists(_hook_file):
573 573 # let's take a look at this hook, maybe it's rhodecode ?
574 574 log.debug('hook exists, checking if it is from rhodecode')
575 575 _HOOK_VER_PAT = re.compile(r'^RC_HOOK_VER')
576 576 with open(_hook_file, 'rb') as f:
577 577 data = f.read()
578 578 matches = re.compile(r'(?:%s)\s*=\s*(.*)'
579 579 % 'RC_HOOK_VER').search(data)
580 580 if matches:
581 581 try:
582 582 ver = matches.groups()[0]
583 583 log.debug('got %s it is rhodecode' % (ver))
584 584 _rhodecode_hook = True
585 585 except:
586 586 log.error(traceback.format_exc())
587 587
588 588 if _rhodecode_hook or force_create:
589 589 log.debug('writing hook file !')
590 590 with open(_hook_file, 'wb') as f:
591 591 tmpl = tmpl.replace('_TMPL_', rhodecode.__version__)
592 592 f.write(tmpl)
593 593 os.chmod(_hook_file, 0755)
594 594 else:
595 log.debug('skipping writing hook file') No newline at end of file
595 log.debug('skipping writing hook file')
General Comments 0
You need to be logged in to leave comments. Login now