##// END OF EJS Templates
git: adjusted code for new libgit2 backend...
marcink -
r3842:8bd67598 default
parent child Browse files
Show More
@@ -35,6 +35,7 b' import urllib'
35 35 import urlobject
36 36 import uuid
37 37 import getpass
38 from functools import update_wrapper, partial
38 39
39 40 import pygments.lexers
40 41 import sqlalchemy
@@ -1027,3 +1028,43 b' def parse_byte_string(size_str):'
1027 1028 _parts = match.groups()
1028 1029 num, type_ = _parts
1029 1030 return long(num) * {'mb': 1024*1024, 'kb': 1024}[type_.lower()]
1031
1032
1033 class CachedProperty(object):
1034 """
1035 Lazy Attributes. With option to invalidate the cache by running a method
1036
1037 class Foo():
1038
1039 @CachedProperty
1040 def heavy_func():
1041 return 'super-calculation'
1042
1043 foo = Foo()
1044 foo.heavy_func() # first computions
1045 foo.heavy_func() # fetch from cache
1046 foo._invalidate_prop_cache('heavy_func')
1047 # at this point calling foo.heavy_func() will be re-computed
1048 """
1049
1050 def __init__(self, func, func_name=None):
1051
1052 if func_name is None:
1053 func_name = func.__name__
1054 self.data = (func, func_name)
1055 update_wrapper(self, func)
1056
1057 def __get__(self, inst, class_):
1058 if inst is None:
1059 return self
1060
1061 func, func_name = self.data
1062 value = func(inst)
1063 inst.__dict__[func_name] = value
1064 if '_invalidate_prop_cache' not in inst.__dict__:
1065 inst.__dict__['_invalidate_prop_cache'] = partial(
1066 self._invalidate_prop_cache, inst)
1067 return value
1068
1069 def _invalidate_prop_cache(self, inst, name):
1070 inst.__dict__.pop(name, None)
@@ -33,12 +33,12 b' import collections'
33 33 import warnings
34 34
35 35 from zope.cachedescriptors.property import Lazy as LazyProperty
36 from zope.cachedescriptors.property import CachedProperty
37 36
38 37 from pyramid import compat
39 38
39 import rhodecode
40 40 from rhodecode.translation import lazy_ugettext
41 from rhodecode.lib.utils2 import safe_str, safe_unicode
41 from rhodecode.lib.utils2 import safe_str, safe_unicode, CachedProperty
42 42 from rhodecode.lib.vcs import connection
43 43 from rhodecode.lib.vcs.utils import author_name, author_email
44 44 from rhodecode.lib.vcs.conf import settings
@@ -264,7 +264,9 b' class BaseRepository(object):'
264 264 EMPTY_COMMIT_ID = '0' * 40
265 265
266 266 path = None
267 _commit_ids_ver = 0
267
268 _is_empty = None
269 _commit_ids = {}
268 270
269 271 def __init__(self, repo_path, config=None, create=False, **kwargs):
270 272 """
@@ -386,8 +388,23 b' class BaseRepository(object):'
386 388 commit = self.get_commit(commit_id)
387 389 return commit.size
388 390
391 def _check_for_empty(self):
392 no_commits = len(self._commit_ids) == 0
393 if no_commits:
394 # check on remote to be sure
395 return self._remote.is_empty()
396 else:
397 return False
398
389 399 def is_empty(self):
390 return self._remote.is_empty()
400 if rhodecode.is_test:
401 return self._check_for_empty()
402
403 if self._is_empty is None:
404 # cache empty for production, but not tests
405 self._is_empty = self._check_for_empty()
406
407 return self._is_empty
391 408
392 409 @staticmethod
393 410 def check_url(url, config):
@@ -408,14 +425,15 b' class BaseRepository(object):'
408 425 # COMMITS
409 426 # ==========================================================================
410 427
411 @CachedProperty('_commit_ids_ver')
428 @CachedProperty
412 429 def commit_ids(self):
413 430 raise NotImplementedError
414 431
415 432 def append_commit_id(self, commit_id):
416 433 if commit_id not in self.commit_ids:
417 434 self._rebuild_cache(self.commit_ids + [commit_id])
418 self._commit_ids_ver = time.time()
435 # clear cache
436 self._invalidate_prop_cache('commit_ids')
419 437
420 438 def get_commit(self, commit_id=None, commit_idx=None, pre_load=None, translate_tag=None):
421 439 """
@@ -46,12 +46,6 b' class GitCommit(base.BaseCommit):'
46 46 """
47 47 Represents state of the repository at single commit id.
48 48 """
49 _author_property = 'author'
50 _committer_property = 'committer'
51 _date_property = 'commit_time'
52 _date_tz_property = 'commit_timezone'
53 _message_property = 'message'
54 _parents_property = 'parents'
55 49
56 50 _filter_pre_load = [
57 51 # done through a more complex tree walk on parents
@@ -124,23 +118,19 b' class GitCommit(base.BaseCommit):'
124 118
125 119 @LazyProperty
126 120 def message(self):
127 return safe_unicode(
128 self._remote.commit_attribute(self.id, self._message_property))
121 return safe_unicode(self._remote.message(self.id))
129 122
130 123 @LazyProperty
131 124 def committer(self):
132 return safe_unicode(
133 self._remote.commit_attribute(self.id, self._committer_property))
125 return safe_unicode(self._remote.author(self.id))
134 126
135 127 @LazyProperty
136 128 def author(self):
137 return safe_unicode(
138 self._remote.commit_attribute(self.id, self._author_property))
129 return safe_unicode(self._remote.author(self.id))
139 130
140 131 @LazyProperty
141 132 def date(self):
142 unix_ts, tz = self._remote.get_object_attrs(
143 self.raw_id, self._date_property, self._date_tz_property)
133 unix_ts, tz = self._remote.date(self.raw_id)
144 134 return utcdate_fromtimestamp(unix_ts, tz)
145 135
146 136 @LazyProperty
@@ -158,13 +148,23 b' class GitCommit(base.BaseCommit):'
158 148 return tags
159 149
160 150 @LazyProperty
161 def branch(self):
151 def commit_branches(self):
152 branches = []
162 153 for name, commit_id in self.repository.branches.iteritems():
163 154 if commit_id == self.raw_id:
164 return safe_unicode(name)
155 branches.append(name)
156 return branches
157
158 @LazyProperty
159 def branch(self):
160 # actually commit can have multiple branches
161 branches = self.commit_branches
162 if branches:
163 return branches[0]
164
165 165 return None
166 166
167 def _get_id_for_path(self, path):
167 def _get_tree_id_for_path(self, path):
168 168 path = safe_str(path)
169 169 if path in self._paths:
170 170 return self._paths[path]
@@ -177,56 +177,26 b' class GitCommit(base.BaseCommit):'
177 177 self._paths[''] = data
178 178 return data
179 179
180 parts = path.split('/')
181 dirs, name = parts[:-1], parts[-1]
182 cur_dir = ''
183
184 # initially extract things from root dir
185 tree_items = self._remote.tree_items(tree_id)
186 self._process_tree_items(tree_items, cur_dir)
180 tree_id, tree_type, tree_mode = \
181 self._remote.tree_and_type_for_path(self.raw_id, path)
182 if tree_id is None:
183 raise self.no_node_at_path(path)
187 184
188 for dir in dirs:
189 if cur_dir:
190 cur_dir = '/'.join((cur_dir, dir))
191 else:
192 cur_dir = dir
193 dir_id = None
194 for item, stat_, id_, type_ in tree_items:
195 if item == dir:
196 dir_id = id_
197 break
198 if dir_id:
199 if type_ != "tree":
200 raise CommitError('%s is not a directory' % cur_dir)
201 # update tree
202 tree_items = self._remote.tree_items(dir_id)
203 else:
204 raise CommitError('%s have not been found' % cur_dir)
205
206 # cache all items from the given traversed tree
207 self._process_tree_items(tree_items, cur_dir)
185 self._paths[path] = [tree_id, tree_type]
186 self._stat_modes[path] = tree_mode
208 187
209 188 if path not in self._paths:
210 189 raise self.no_node_at_path(path)
211 190
212 191 return self._paths[path]
213 192
214 def _process_tree_items(self, items, cur_dir):
215 for item, stat_, id_, type_ in items:
216 if cur_dir:
217 name = '/'.join((cur_dir, item))
218 else:
219 name = item
220 self._paths[name] = [id_, type_]
221 self._stat_modes[name] = stat_
222
223 193 def _get_kind(self, path):
224 path_id, type_ = self._get_id_for_path(path)
194 tree_id, type_ = self._get_tree_id_for_path(path)
225 195 if type_ == 'blob':
226 196 return NodeKind.FILE
227 197 elif type_ == 'tree':
228 198 return NodeKind.DIR
229 elif type == 'link':
199 elif type_ == 'link':
230 200 return NodeKind.SUBMODULE
231 201 return None
232 202
@@ -245,8 +215,7 b' class GitCommit(base.BaseCommit):'
245 215 """
246 216 Returns list of parent commits.
247 217 """
248 parent_ids = self._remote.commit_attribute(
249 self.id, self._parents_property)
218 parent_ids = self._remote.parents(self.id)
250 219 return self._make_commits(parent_ids)
251 220
252 221 @LazyProperty
@@ -266,11 +235,11 b' class GitCommit(base.BaseCommit):'
266 235 child_ids.extend(found_ids)
267 236 return self._make_commits(child_ids)
268 237
269 def _make_commits(self, commit_ids, pre_load=None):
270 return [
271 self.repository.get_commit(commit_id=commit_id, pre_load=pre_load,
272 translate_tag=False)
273 for commit_id in commit_ids]
238 def _make_commits(self, commit_ids):
239 def commit_maker(_commit_id):
240 return self.repository.get_commit(commit_id=commit_id)
241
242 return [commit_maker(commit_id) for commit_id in commit_ids]
274 243
275 244 def get_file_mode(self, path):
276 245 """
@@ -278,7 +247,7 b' class GitCommit(base.BaseCommit):'
278 247 """
279 248 path = safe_str(path)
280 249 # ensure path is traversed
281 self._get_id_for_path(path)
250 self._get_tree_id_for_path(path)
282 251 return self._stat_modes[path]
283 252
284 253 def is_link(self, path):
@@ -288,15 +257,15 b' class GitCommit(base.BaseCommit):'
288 257 """
289 258 Returns content of the file at given `path`.
290 259 """
291 id_, _ = self._get_id_for_path(path)
292 return self._remote.blob_as_pretty_string(id_)
260 tree_id, _ = self._get_tree_id_for_path(path)
261 return self._remote.blob_as_pretty_string(tree_id)
293 262
294 263 def get_file_size(self, path):
295 264 """
296 265 Returns size of the file at given `path`.
297 266 """
298 id_, _ = self._get_id_for_path(path)
299 return self._remote.blob_raw_length(id_)
267 tree_id, _ = self._get_tree_id_for_path(path)
268 return self._remote.blob_raw_length(tree_id)
300 269
301 270 def get_path_history(self, path, limit=None, pre_load=None):
302 271 """
@@ -350,20 +319,23 b' class GitCommit(base.BaseCommit):'
350 319 line)
351 320
352 321 def get_nodes(self, path):
322
353 323 if self._get_kind(path) != NodeKind.DIR:
354 324 raise CommitError(
355 325 "Directory does not exist for commit %s at '%s'" % (self.raw_id, path))
356 326 path = self._fix_path(path)
357 id_, _ = self._get_id_for_path(path)
358 tree_id = self._remote[id_]['id']
327
328 tree_id, _ = self._get_tree_id_for_path(path)
329
359 330 dirnodes = []
360 331 filenodes = []
361 alias = self.repository.alias
332
333 # extracted tree ID gives us our files...
362 334 for name, stat_, id_, type_ in self._remote.tree_items(tree_id):
363 335 if type_ == 'link':
364 336 url = self._get_submodule_url('/'.join((path, name)))
365 337 dirnodes.append(SubModuleNode(
366 name, url=url, commit=id_, alias=alias))
338 name, url=url, commit=id_, alias=self.repository.alias))
367 339 continue
368 340
369 341 if path != '':
@@ -394,7 +366,7 b' class GitCommit(base.BaseCommit):'
394 366 path = self._fix_path(path)
395 367 if path not in self.nodes:
396 368 try:
397 id_, type_ = self._get_id_for_path(path)
369 tree_id, type_ = self._get_tree_id_for_path(path)
398 370 except CommitError:
399 371 raise NodeDoesNotExistError(
400 372 "Cannot find one of parents' directories for a given "
@@ -402,7 +374,7 b' class GitCommit(base.BaseCommit):'
402 374
403 375 if type_ == 'link':
404 376 url = self._get_submodule_url(path)
405 node = SubModuleNode(path, url=url, commit=id_,
377 node = SubModuleNode(path, url=url, commit=tree_id,
406 378 alias=self.repository.alias)
407 379 elif type_ == 'tree':
408 380 if path == '':
@@ -411,16 +383,18 b' class GitCommit(base.BaseCommit):'
411 383 node = DirNode(path, commit=self)
412 384 elif type_ == 'blob':
413 385 node = FileNode(path, commit=self, pre_load=pre_load)
386 self._stat_modes[path] = node.mode
414 387 else:
415 388 raise self.no_node_at_path(path)
416 389
417 390 # cache node
418 391 self.nodes[path] = node
392
419 393 return self.nodes[path]
420 394
421 395 def get_largefile_node(self, path):
422 id_, _ = self._get_id_for_path(path)
423 pointer_spec = self._remote.is_large_file(id_)
396 tree_id, _ = self._get_tree_id_for_path(path)
397 pointer_spec = self._remote.is_large_file(tree_id)
424 398
425 399 if pointer_spec:
426 400 # content of that file regular FileNode is the hash of largefile
@@ -25,15 +25,14 b' GIT repository module'
25 25 import logging
26 26 import os
27 27 import re
28 import time
29 28
30 29 from zope.cachedescriptors.property import Lazy as LazyProperty
31 from zope.cachedescriptors.property import CachedProperty
32 30
33 31 from rhodecode.lib.compat import OrderedDict
34 32 from rhodecode.lib.datelib import (
35 33 utcdate_fromtimestamp, makedate, date_astimestamp)
36 34 from rhodecode.lib.utils import safe_unicode, safe_str
35 from rhodecode.lib.utils2 import CachedProperty
37 36 from rhodecode.lib.vcs import connection, path as vcspath
38 37 from rhodecode.lib.vcs.backends.base import (
39 38 BaseRepository, CollectionGenerator, Config, MergeResponse,
@@ -71,9 +70,6 b' class GitRepository(BaseRepository):'
71 70 # caches
72 71 self._commit_ids = {}
73 72
74 # dependent that trigger re-computation of commit_ids
75 self._commit_ids_ver = 0
76
77 73 @LazyProperty
78 74 def _remote(self):
79 75 return connection.Git(self.path, self.config, with_wire=self.with_wire)
@@ -86,7 +82,7 b' class GitRepository(BaseRepository):'
86 82 def head(self):
87 83 return self._remote.head()
88 84
89 @CachedProperty('_commit_ids_ver')
85 @CachedProperty
90 86 def commit_ids(self):
91 87 """
92 88 Returns list of commit ids, in ascending order. Being lazy
@@ -190,12 +186,16 b' class GitRepository(BaseRepository):'
190 186 except OSError as err:
191 187 raise RepositoryError(err)
192 188
193 def _get_all_commit_ids(self, filters=None):
189 def _get_all_commit_ids(self):
190 return self._remote.get_all_commit_ids()
191
192 def _get_commit_ids(self, filters=None):
194 193 # we must check if this repo is not empty, since later command
195 194 # fails if it is. And it's cheaper to ask than throw the subprocess
196 195 # errors
197 196
198 197 head = self._remote.head(show_exc=False)
198
199 199 if not head:
200 200 return []
201 201
@@ -208,7 +208,7 b' class GitRepository(BaseRepository):'
208 208 if filters.get('until'):
209 209 extra_filter.append('--until=%s' % (filters['until']))
210 210 if filters.get('branch_name'):
211 rev_filter = ['--tags']
211 rev_filter = []
212 212 extra_filter.append(filters['branch_name'])
213 213 rev_filter.extend(extra_filter)
214 214
@@ -233,6 +233,8 b' class GitRepository(BaseRepository):'
233 233
234 234 if commit_id_or_idx in (None, '', 'tip', 'HEAD', 'head', -1):
235 235 return self.commit_ids[-1]
236 commit_missing_err = "Commit {} does not exist for `{}`".format(
237 *map(safe_str, [commit_id_or_idx, self.name]))
236 238
237 239 is_bstr = isinstance(commit_id_or_idx, (str, unicode))
238 240 if ((is_bstr and commit_id_or_idx.isdigit() and len(commit_id_or_idx) < 12)
@@ -240,30 +242,15 b' class GitRepository(BaseRepository):'
240 242 try:
241 243 commit_id_or_idx = self.commit_ids[int(commit_id_or_idx)]
242 244 except Exception:
243 msg = "Commit {} does not exist for `{}`".format(commit_id_or_idx, self.name)
244 raise CommitDoesNotExistError(msg)
245 raise CommitDoesNotExistError(commit_missing_err)
245 246
246 247 elif is_bstr:
247 # check full path ref, eg. refs/heads/master
248 ref_id = self._refs.get(commit_id_or_idx)
249 if ref_id:
250 return ref_id
251
252 # check branch name
253 branch_ids = self.branches.values()
254 ref_id = self._refs.get('refs/heads/%s' % commit_id_or_idx)
255 if ref_id:
256 return ref_id
257
258 # check tag name
259 ref_id = self._refs.get('refs/tags/%s' % commit_id_or_idx)
260 if ref_id:
261 return ref_id
262
263 if (not SHA_PATTERN.match(commit_id_or_idx) or
264 commit_id_or_idx not in self.commit_ids):
265 msg = "Commit {} does not exist for `{}`".format(commit_id_or_idx, self.name)
266 raise CommitDoesNotExistError(msg)
248 # Need to call remote to translate id for tagging scenario
249 try:
250 remote_data = self._remote.get_object(commit_id_or_idx)
251 commit_id_or_idx = remote_data["commit_id"]
252 except (CommitDoesNotExistError,):
253 raise CommitDoesNotExistError(commit_missing_err)
267 254
268 255 # Ensure we return full id
269 256 if not SHA_PATTERN.match(str(commit_id_or_idx)):
@@ -327,32 +314,31 b' class GitRepository(BaseRepository):'
327 314 def _get_branches(self):
328 315 return self._get_refs_entries(prefix='refs/heads/', strip_prefix=True)
329 316
330 @LazyProperty
317 @CachedProperty
331 318 def branches(self):
332 319 return self._get_branches()
333 320
334 @LazyProperty
321 @CachedProperty
335 322 def branches_closed(self):
336 323 return {}
337 324
338 @LazyProperty
325 @CachedProperty
339 326 def bookmarks(self):
340 327 return {}
341 328
342 @LazyProperty
329 @CachedProperty
343 330 def branches_all(self):
344 331 all_branches = {}
345 332 all_branches.update(self.branches)
346 333 all_branches.update(self.branches_closed)
347 334 return all_branches
348 335
349 @LazyProperty
336 @CachedProperty
350 337 def tags(self):
351 338 return self._get_tags()
352 339
353 340 def _get_tags(self):
354 return self._get_refs_entries(
355 prefix='refs/tags/', strip_prefix=True, reverse=True)
341 return self._get_refs_entries(prefix='refs/tags/', strip_prefix=True, reverse=True)
356 342
357 343 def tag(self, name, user, commit_id=None, message=None, date=None,
358 344 **kwargs):
@@ -368,15 +354,17 b' class GitRepository(BaseRepository):'
368 354
369 355 :raises TagAlreadyExistError: if tag with same name already exists
370 356 """
357 print self._refs
371 358 if name in self.tags:
372 359 raise TagAlreadyExistError("Tag %s already exists" % name)
373 360 commit = self.get_commit(commit_id=commit_id)
374 message = message or "Added tag %s for commit %s" % (
375 name, commit.raw_id)
376 self._remote.set_refs('refs/tags/%s' % name, commit._commit['id'])
361 message = message or "Added tag %s for commit %s" % (name, commit.raw_id)
362
363 self._remote.set_refs('refs/tags/%s' % name, commit.raw_id)
377 364
378 self._refs = self._get_refs()
379 self.tags = self._get_tags()
365 self._invalidate_prop_cache('tags')
366 self._invalidate_prop_cache('_refs')
367
380 368 return commit
381 369
382 370 def remove_tag(self, name, user, message=None, date=None):
@@ -392,19 +380,15 b' class GitRepository(BaseRepository):'
392 380 """
393 381 if name not in self.tags:
394 382 raise TagDoesNotExistError("Tag %s does not exist" % name)
395 tagpath = vcspath.join(
396 self._remote.get_refs_path(), 'refs', 'tags', name)
397 try:
398 os.remove(tagpath)
399 self._refs = self._get_refs()
400 self.tags = self._get_tags()
401 except OSError as e:
402 raise RepositoryError(e.strerror)
383
384 self._remote.tag_remove(name)
385 self._invalidate_prop_cache('tags')
386 self._invalidate_prop_cache('_refs')
403 387
404 388 def _get_refs(self):
405 389 return self._remote.get_refs()
406 390
407 @LazyProperty
391 @CachedProperty
408 392 def _refs(self):
409 393 return self._get_refs()
410 394
@@ -455,18 +439,13 b' class GitRepository(BaseRepository):'
455 439 else:
456 440 commit_id = "tip"
457 441
458 commit_id = self._lookup_commit(commit_id)
459 remote_idx = None
460 442 if translate_tag:
461 # Need to call remote to translate id for tagging scenario
462 remote_data = self._remote.get_object(commit_id)
463 commit_id = remote_data["commit_id"]
464 remote_idx = remote_data["idx"]
443 commit_id = self._lookup_commit(commit_id)
465 444
466 445 try:
467 446 idx = self._commit_ids[commit_id]
468 447 except KeyError:
469 idx = remote_idx or 0
448 idx = -1
470 449
471 450 return GitCommit(self, commit_id, idx, pre_load=pre_load)
472 451
@@ -539,14 +518,8 b' class GitRepository(BaseRepository):'
539 518 'start': start_pos,
540 519 'end': end_pos,
541 520 }
542 commit_ids = self._get_all_commit_ids(filters=revfilters)
521 commit_ids = self._get_commit_ids(filters=revfilters)
543 522
544 # pure python stuff, it's slow due to walker walking whole repo
545 # def get_revs(walker):
546 # for walker_entry in walker:
547 # yield walker_entry.commit.id
548 # revfilters = {}
549 # commit_ids = list(reversed(list(get_revs(self._repo.get_walker(**revfilters)))))
550 523 else:
551 524 commit_ids = self.commit_ids
552 525
@@ -613,8 +586,11 b' class GitRepository(BaseRepository):'
613 586 commit = commit.parents[0]
614 587 self._remote.set_refs('refs/heads/%s' % branch_name, commit.raw_id)
615 588
616 self._commit_ids_ver = time.time()
617 # we updated _commit_ids_ver so accessing self.commit_ids will re-compute it
589 # clear cached properties
590 self._invalidate_prop_cache('commit_ids')
591 self._invalidate_prop_cache('_refs')
592 self._invalidate_prop_cache('branches')
593
618 594 return len(self.commit_ids)
619 595
620 596 def get_common_ancestor(self, commit_id1, commit_id2, repo2):
@@ -697,9 +673,11 b' class GitRepository(BaseRepository):'
697 673
698 674 def set_refs(self, ref_name, commit_id):
699 675 self._remote.set_refs(ref_name, commit_id)
676 self._invalidate_prop_cache('_refs')
700 677
701 678 def remove_ref(self, ref_name):
702 679 self._remote.remove_ref(ref_name)
680 self._invalidate_prop_cache('_refs')
703 681
704 682 def _update_server_info(self):
705 683 """
@@ -744,6 +722,12 b' class GitRepository(BaseRepository):'
744 722 cmd.append(branch_name)
745 723 self.run_git_command(cmd, fail_on_stderr=False)
746 724
725 def _create_branch(self, branch_name, commit_id):
726 """
727 creates a branch in a GIT repo
728 """
729 self._remote.create_branch(branch_name, commit_id)
730
747 731 def _identify(self):
748 732 """
749 733 Return the current state of the working directory.
@@ -299,10 +299,11 b' class MercurialCommit(base.BaseCommit):'
299 299 loc = vals[0]
300 300 commit = vals[1]
301 301 dirnodes.append(SubModuleNode(k, url=loc, commit=commit, alias=alias))
302
302 303 nodes = dirnodes + filenodes
303 # cache nodes
304 304 for node in nodes:
305 self.nodes[node.path] = node
305 if node.path not in self.nodes:
306 self.nodes[node.path] = node
306 307 nodes.sort()
307 308
308 309 return nodes
@@ -24,16 +24,15 b' HG repository module'
24 24 import os
25 25 import logging
26 26 import binascii
27 import time
28 27 import urllib
29 28
30 29 from zope.cachedescriptors.property import Lazy as LazyProperty
31 from zope.cachedescriptors.property import CachedProperty
32 30
33 31 from rhodecode.lib.compat import OrderedDict
34 32 from rhodecode.lib.datelib import (
35 33 date_to_timestamp_plus_offset, utcdate_fromtimestamp, makedate)
36 34 from rhodecode.lib.utils import safe_unicode, safe_str
35 from rhodecode.lib.utils2 import CachedProperty
37 36 from rhodecode.lib.vcs import connection, exceptions
38 37 from rhodecode.lib.vcs.backends.base import (
39 38 BaseRepository, CollectionGenerator, Config, MergeResponse,
@@ -87,14 +86,11 b' class MercurialRepository(BaseRepository'
87 86 # caches
88 87 self._commit_ids = {}
89 88
90 # dependent that trigger re-computation of commit_ids
91 self._commit_ids_ver = 0
92
93 89 @LazyProperty
94 90 def _remote(self):
95 91 return connection.Hg(self.path, self.config, with_wire=self.with_wire)
96 92
97 @CachedProperty('_commit_ids_ver')
93 @CachedProperty
98 94 def commit_ids(self):
99 95 """
100 96 Returns list of commit ids, in ascending order. Being lazy
@@ -108,15 +104,15 b' class MercurialRepository(BaseRepository'
108 104 self._commit_ids = dict((commit_id, index)
109 105 for index, commit_id in enumerate(commit_ids))
110 106
111 @LazyProperty
107 @CachedProperty
112 108 def branches(self):
113 109 return self._get_branches()
114 110
115 @LazyProperty
111 @CachedProperty
116 112 def branches_closed(self):
117 113 return self._get_branches(active=False, closed=True)
118 114
119 @LazyProperty
115 @CachedProperty
120 116 def branches_all(self):
121 117 all_branches = {}
122 118 all_branches.update(self.branches)
@@ -143,7 +139,7 b' class MercurialRepository(BaseRepository'
143 139
144 140 return OrderedDict(sorted(_branches, key=get_name, reverse=False))
145 141
146 @LazyProperty
142 @CachedProperty
147 143 def tags(self):
148 144 """
149 145 Gets tags for this repository
@@ -276,8 +272,9 b' class MercurialRepository(BaseRepository'
276 272 self._remote.strip(commit_id, update=False, backup="none")
277 273
278 274 self._remote.invalidate_vcs_cache()
279 self._commit_ids_ver = time.time()
280 # we updated _commit_ids_ver so accessing self.commit_ids will re-compute it
275 # clear cache
276 self._invalidate_prop_cache('commit_ids')
277
281 278 return len(self.commit_ids)
282 279
283 280 def verify(self):
@@ -27,11 +27,11 b' import os'
27 27 import urllib
28 28
29 29 from zope.cachedescriptors.property import Lazy as LazyProperty
30 from zope.cachedescriptors.property import CachedProperty
31 30
32 31 from rhodecode.lib.compat import OrderedDict
33 32 from rhodecode.lib.datelib import date_astimestamp
34 33 from rhodecode.lib.utils import safe_str, safe_unicode
34 from rhodecode.lib.utils2 import CachedProperty
35 35 from rhodecode.lib.vcs import connection, path as vcspath
36 36 from rhodecode.lib.vcs.backends import base
37 37 from rhodecode.lib.vcs.backends.svn.commit import (
@@ -76,8 +76,9 b' class SubversionRepository(base.BaseRepo'
76 76
77 77 self._init_repo(create, src_url)
78 78
79 # dependent that trigger re-computation of commit_ids
80 self._commit_ids_ver = 0
79 # caches
80 self._commit_ids = {}
81
81 82
82 83 @LazyProperty
83 84 def _remote(self):
@@ -97,7 +98,7 b' class SubversionRepository(base.BaseRepo'
97 98 else:
98 99 self._check_path()
99 100
100 @CachedProperty('_commit_ids_ver')
101 @CachedProperty
101 102 def commit_ids(self):
102 103 head = self._remote.lookup(None)
103 104 return [str(r) for r in xrange(1, head + 1)]
@@ -46,6 +46,7 b' class TestGitRepository(object):'
46 46 @pytest.fixture(autouse=True)
47 47 def prepare(self, request, baseapp):
48 48 self.repo = GitRepository(TEST_GIT_REPO, bare=True)
49 self.repo.count()
49 50
50 51 def get_clone_repo(self, tmp_path_factory):
51 52 """
@@ -1242,7 +1243,7 b' class TestGetSubmoduleUrl(object):'
1242 1243 commit = GitCommit(repository=repository, raw_id='abcdef12', idx=1)
1243 1244 submodule_url = 'https://code.rhodecode.com/dulwich'
1244 1245 get_id_patch = mock.patch.object(
1245 commit, '_get_id_for_path', return_value=(1, 'link'))
1246 commit, '_get_tree_id_for_path', return_value=(1, 'link'))
1246 1247 get_submodule_patch = mock.patch.object(
1247 1248 commit, '_get_submodule_url', return_value=submodule_url)
1248 1249
@@ -1262,7 +1263,7 b' class TestGetSubmoduleUrl(object):'
1262 1263 commit = GitCommit(repository=repository, raw_id='abcdef12', idx=1)
1263 1264 submodule_url = 'https://code.rhodecode.com/dulwich'
1264 1265 get_id_patch = mock.patch.object(
1265 commit, '_get_id_for_path', return_value=(1, 'tree'))
1266 commit, '_get_tree_id_for_path', return_value=(1, 'tree'))
1266 1267 get_submodule_patch = mock.patch.object(
1267 1268 commit, '_get_submodule_url', return_value=submodule_url)
1268 1269
@@ -88,8 +88,6 b' class TestInMemoryCommit(BackendTestMixi'
88 88
89 89 @pytest.mark.backends("git")
90 90 def test_add_on_branch_git(self, nodes):
91 self.repo._checkout('stable', create=True)
92
93 91 for node in nodes:
94 92 self.imc.add(node)
95 93 self.commit(branch=u'stable')
General Comments 0
You need to be logged in to leave comments. Login now