git: adjusted code for new libgit2 backend
- made @CachedProperty use a custom decarator that can do invalidations. This is required for tests - made few cleanups of code since we use a simpler libgit2 backend now - removed some unused obsolete code
This commit is contained in:
parent
94390f644f
commit
ccfa86d740
9 changed files with 185 additions and 170 deletions
|
|
@ -35,6 +35,7 @@ import urllib
|
|||
import urlobject
|
||||
import uuid
|
||||
import getpass
|
||||
from functools import update_wrapper, partial
|
||||
|
||||
import pygments.lexers
|
||||
import sqlalchemy
|
||||
|
|
@ -1027,3 +1028,43 @@ def parse_byte_string(size_str):
|
|||
_parts = match.groups()
|
||||
num, type_ = _parts
|
||||
return long(num) * {'mb': 1024*1024, 'kb': 1024}[type_.lower()]
|
||||
|
||||
|
||||
class CachedProperty(object):
|
||||
"""
|
||||
Lazy Attributes. With option to invalidate the cache by running a method
|
||||
|
||||
class Foo():
|
||||
|
||||
@CachedProperty
|
||||
def heavy_func():
|
||||
return 'super-calculation'
|
||||
|
||||
foo = Foo()
|
||||
foo.heavy_func() # first computions
|
||||
foo.heavy_func() # fetch from cache
|
||||
foo._invalidate_prop_cache('heavy_func')
|
||||
# at this point calling foo.heavy_func() will be re-computed
|
||||
"""
|
||||
|
||||
def __init__(self, func, func_name=None):
|
||||
|
||||
if func_name is None:
|
||||
func_name = func.__name__
|
||||
self.data = (func, func_name)
|
||||
update_wrapper(self, func)
|
||||
|
||||
def __get__(self, inst, class_):
|
||||
if inst is None:
|
||||
return self
|
||||
|
||||
func, func_name = self.data
|
||||
value = func(inst)
|
||||
inst.__dict__[func_name] = value
|
||||
if '_invalidate_prop_cache' not in inst.__dict__:
|
||||
inst.__dict__['_invalidate_prop_cache'] = partial(
|
||||
self._invalidate_prop_cache, inst)
|
||||
return value
|
||||
|
||||
def _invalidate_prop_cache(self, inst, name):
|
||||
inst.__dict__.pop(name, None)
|
||||
|
|
|
|||
|
|
@ -33,12 +33,12 @@ import collections
|
|||
import warnings
|
||||
|
||||
from zope.cachedescriptors.property import Lazy as LazyProperty
|
||||
from zope.cachedescriptors.property import CachedProperty
|
||||
|
||||
from pyramid import compat
|
||||
|
||||
import rhodecode
|
||||
from rhodecode.translation import lazy_ugettext
|
||||
from rhodecode.lib.utils2 import safe_str, safe_unicode
|
||||
from rhodecode.lib.utils2 import safe_str, safe_unicode, CachedProperty
|
||||
from rhodecode.lib.vcs import connection
|
||||
from rhodecode.lib.vcs.utils import author_name, author_email
|
||||
from rhodecode.lib.vcs.conf import settings
|
||||
|
|
@ -264,7 +264,9 @@ class BaseRepository(object):
|
|||
EMPTY_COMMIT_ID = '0' * 40
|
||||
|
||||
path = None
|
||||
_commit_ids_ver = 0
|
||||
|
||||
_is_empty = None
|
||||
_commit_ids = {}
|
||||
|
||||
def __init__(self, repo_path, config=None, create=False, **kwargs):
|
||||
"""
|
||||
|
|
@ -386,8 +388,23 @@ class BaseRepository(object):
|
|||
commit = self.get_commit(commit_id)
|
||||
return commit.size
|
||||
|
||||
def _check_for_empty(self):
|
||||
no_commits = len(self._commit_ids) == 0
|
||||
if no_commits:
|
||||
# check on remote to be sure
|
||||
return self._remote.is_empty()
|
||||
else:
|
||||
return False
|
||||
|
||||
def is_empty(self):
|
||||
return self._remote.is_empty()
|
||||
if rhodecode.is_test:
|
||||
return self._check_for_empty()
|
||||
|
||||
if self._is_empty is None:
|
||||
# cache empty for production, but not tests
|
||||
self._is_empty = self._check_for_empty()
|
||||
|
||||
return self._is_empty
|
||||
|
||||
@staticmethod
|
||||
def check_url(url, config):
|
||||
|
|
@ -408,14 +425,15 @@ class BaseRepository(object):
|
|||
# COMMITS
|
||||
# ==========================================================================
|
||||
|
||||
@CachedProperty('_commit_ids_ver')
|
||||
@CachedProperty
|
||||
def commit_ids(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def append_commit_id(self, commit_id):
|
||||
if commit_id not in self.commit_ids:
|
||||
self._rebuild_cache(self.commit_ids + [commit_id])
|
||||
self._commit_ids_ver = time.time()
|
||||
# clear cache
|
||||
self._invalidate_prop_cache('commit_ids')
|
||||
|
||||
def get_commit(self, commit_id=None, commit_idx=None, pre_load=None, translate_tag=None):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -46,12 +46,6 @@ class GitCommit(base.BaseCommit):
|
|||
"""
|
||||
Represents state of the repository at single commit id.
|
||||
"""
|
||||
_author_property = 'author'
|
||||
_committer_property = 'committer'
|
||||
_date_property = 'commit_time'
|
||||
_date_tz_property = 'commit_timezone'
|
||||
_message_property = 'message'
|
||||
_parents_property = 'parents'
|
||||
|
||||
_filter_pre_load = [
|
||||
# done through a more complex tree walk on parents
|
||||
|
|
@ -124,23 +118,19 @@ class GitCommit(base.BaseCommit):
|
|||
|
||||
@LazyProperty
|
||||
def message(self):
|
||||
return safe_unicode(
|
||||
self._remote.commit_attribute(self.id, self._message_property))
|
||||
return safe_unicode(self._remote.message(self.id))
|
||||
|
||||
@LazyProperty
|
||||
def committer(self):
|
||||
return safe_unicode(
|
||||
self._remote.commit_attribute(self.id, self._committer_property))
|
||||
return safe_unicode(self._remote.author(self.id))
|
||||
|
||||
@LazyProperty
|
||||
def author(self):
|
||||
return safe_unicode(
|
||||
self._remote.commit_attribute(self.id, self._author_property))
|
||||
return safe_unicode(self._remote.author(self.id))
|
||||
|
||||
@LazyProperty
|
||||
def date(self):
|
||||
unix_ts, tz = self._remote.get_object_attrs(
|
||||
self.raw_id, self._date_property, self._date_tz_property)
|
||||
unix_ts, tz = self._remote.date(self.raw_id)
|
||||
return utcdate_fromtimestamp(unix_ts, tz)
|
||||
|
||||
@LazyProperty
|
||||
|
|
@ -158,13 +148,23 @@ class GitCommit(base.BaseCommit):
|
|||
return tags
|
||||
|
||||
@LazyProperty
|
||||
def branch(self):
|
||||
def commit_branches(self):
|
||||
branches = []
|
||||
for name, commit_id in self.repository.branches.iteritems():
|
||||
if commit_id == self.raw_id:
|
||||
return safe_unicode(name)
|
||||
branches.append(name)
|
||||
return branches
|
||||
|
||||
@LazyProperty
|
||||
def branch(self):
|
||||
# actually commit can have multiple branches
|
||||
branches = self.commit_branches
|
||||
if branches:
|
||||
return branches[0]
|
||||
|
||||
return None
|
||||
|
||||
def _get_id_for_path(self, path):
|
||||
def _get_tree_id_for_path(self, path):
|
||||
path = safe_str(path)
|
||||
if path in self._paths:
|
||||
return self._paths[path]
|
||||
|
|
@ -177,56 +177,26 @@ class GitCommit(base.BaseCommit):
|
|||
self._paths[''] = data
|
||||
return data
|
||||
|
||||
parts = path.split('/')
|
||||
dirs, name = parts[:-1], parts[-1]
|
||||
cur_dir = ''
|
||||
tree_id, tree_type, tree_mode = \
|
||||
self._remote.tree_and_type_for_path(self.raw_id, path)
|
||||
if tree_id is None:
|
||||
raise self.no_node_at_path(path)
|
||||
|
||||
# initially extract things from root dir
|
||||
tree_items = self._remote.tree_items(tree_id)
|
||||
self._process_tree_items(tree_items, cur_dir)
|
||||
|
||||
for dir in dirs:
|
||||
if cur_dir:
|
||||
cur_dir = '/'.join((cur_dir, dir))
|
||||
else:
|
||||
cur_dir = dir
|
||||
dir_id = None
|
||||
for item, stat_, id_, type_ in tree_items:
|
||||
if item == dir:
|
||||
dir_id = id_
|
||||
break
|
||||
if dir_id:
|
||||
if type_ != "tree":
|
||||
raise CommitError('%s is not a directory' % cur_dir)
|
||||
# update tree
|
||||
tree_items = self._remote.tree_items(dir_id)
|
||||
else:
|
||||
raise CommitError('%s have not been found' % cur_dir)
|
||||
|
||||
# cache all items from the given traversed tree
|
||||
self._process_tree_items(tree_items, cur_dir)
|
||||
self._paths[path] = [tree_id, tree_type]
|
||||
self._stat_modes[path] = tree_mode
|
||||
|
||||
if path not in self._paths:
|
||||
raise self.no_node_at_path(path)
|
||||
|
||||
return self._paths[path]
|
||||
|
||||
def _process_tree_items(self, items, cur_dir):
|
||||
for item, stat_, id_, type_ in items:
|
||||
if cur_dir:
|
||||
name = '/'.join((cur_dir, item))
|
||||
else:
|
||||
name = item
|
||||
self._paths[name] = [id_, type_]
|
||||
self._stat_modes[name] = stat_
|
||||
|
||||
def _get_kind(self, path):
|
||||
path_id, type_ = self._get_id_for_path(path)
|
||||
tree_id, type_ = self._get_tree_id_for_path(path)
|
||||
if type_ == 'blob':
|
||||
return NodeKind.FILE
|
||||
elif type_ == 'tree':
|
||||
return NodeKind.DIR
|
||||
elif type == 'link':
|
||||
elif type_ == 'link':
|
||||
return NodeKind.SUBMODULE
|
||||
return None
|
||||
|
||||
|
|
@ -245,8 +215,7 @@ class GitCommit(base.BaseCommit):
|
|||
"""
|
||||
Returns list of parent commits.
|
||||
"""
|
||||
parent_ids = self._remote.commit_attribute(
|
||||
self.id, self._parents_property)
|
||||
parent_ids = self._remote.parents(self.id)
|
||||
return self._make_commits(parent_ids)
|
||||
|
||||
@LazyProperty
|
||||
|
|
@ -266,11 +235,11 @@ class GitCommit(base.BaseCommit):
|
|||
child_ids.extend(found_ids)
|
||||
return self._make_commits(child_ids)
|
||||
|
||||
def _make_commits(self, commit_ids, pre_load=None):
|
||||
return [
|
||||
self.repository.get_commit(commit_id=commit_id, pre_load=pre_load,
|
||||
translate_tag=False)
|
||||
for commit_id in commit_ids]
|
||||
def _make_commits(self, commit_ids):
|
||||
def commit_maker(_commit_id):
|
||||
return self.repository.get_commit(commit_id=commit_id)
|
||||
|
||||
return [commit_maker(commit_id) for commit_id in commit_ids]
|
||||
|
||||
def get_file_mode(self, path):
|
||||
"""
|
||||
|
|
@ -278,7 +247,7 @@ class GitCommit(base.BaseCommit):
|
|||
"""
|
||||
path = safe_str(path)
|
||||
# ensure path is traversed
|
||||
self._get_id_for_path(path)
|
||||
self._get_tree_id_for_path(path)
|
||||
return self._stat_modes[path]
|
||||
|
||||
def is_link(self, path):
|
||||
|
|
@ -288,15 +257,15 @@ class GitCommit(base.BaseCommit):
|
|||
"""
|
||||
Returns content of the file at given `path`.
|
||||
"""
|
||||
id_, _ = self._get_id_for_path(path)
|
||||
return self._remote.blob_as_pretty_string(id_)
|
||||
tree_id, _ = self._get_tree_id_for_path(path)
|
||||
return self._remote.blob_as_pretty_string(tree_id)
|
||||
|
||||
def get_file_size(self, path):
|
||||
"""
|
||||
Returns size of the file at given `path`.
|
||||
"""
|
||||
id_, _ = self._get_id_for_path(path)
|
||||
return self._remote.blob_raw_length(id_)
|
||||
tree_id, _ = self._get_tree_id_for_path(path)
|
||||
return self._remote.blob_raw_length(tree_id)
|
||||
|
||||
def get_path_history(self, path, limit=None, pre_load=None):
|
||||
"""
|
||||
|
|
@ -350,20 +319,23 @@ class GitCommit(base.BaseCommit):
|
|||
line)
|
||||
|
||||
def get_nodes(self, path):
|
||||
|
||||
if self._get_kind(path) != NodeKind.DIR:
|
||||
raise CommitError(
|
||||
"Directory does not exist for commit %s at '%s'" % (self.raw_id, path))
|
||||
path = self._fix_path(path)
|
||||
id_, _ = self._get_id_for_path(path)
|
||||
tree_id = self._remote[id_]['id']
|
||||
|
||||
tree_id, _ = self._get_tree_id_for_path(path)
|
||||
|
||||
dirnodes = []
|
||||
filenodes = []
|
||||
alias = self.repository.alias
|
||||
|
||||
# extracted tree ID gives us our files...
|
||||
for name, stat_, id_, type_ in self._remote.tree_items(tree_id):
|
||||
if type_ == 'link':
|
||||
url = self._get_submodule_url('/'.join((path, name)))
|
||||
dirnodes.append(SubModuleNode(
|
||||
name, url=url, commit=id_, alias=alias))
|
||||
name, url=url, commit=id_, alias=self.repository.alias))
|
||||
continue
|
||||
|
||||
if path != '':
|
||||
|
|
@ -394,7 +366,7 @@ class GitCommit(base.BaseCommit):
|
|||
path = self._fix_path(path)
|
||||
if path not in self.nodes:
|
||||
try:
|
||||
id_, type_ = self._get_id_for_path(path)
|
||||
tree_id, type_ = self._get_tree_id_for_path(path)
|
||||
except CommitError:
|
||||
raise NodeDoesNotExistError(
|
||||
"Cannot find one of parents' directories for a given "
|
||||
|
|
@ -402,7 +374,7 @@ class GitCommit(base.BaseCommit):
|
|||
|
||||
if type_ == 'link':
|
||||
url = self._get_submodule_url(path)
|
||||
node = SubModuleNode(path, url=url, commit=id_,
|
||||
node = SubModuleNode(path, url=url, commit=tree_id,
|
||||
alias=self.repository.alias)
|
||||
elif type_ == 'tree':
|
||||
if path == '':
|
||||
|
|
@ -411,16 +383,18 @@ class GitCommit(base.BaseCommit):
|
|||
node = DirNode(path, commit=self)
|
||||
elif type_ == 'blob':
|
||||
node = FileNode(path, commit=self, pre_load=pre_load)
|
||||
self._stat_modes[path] = node.mode
|
||||
else:
|
||||
raise self.no_node_at_path(path)
|
||||
|
||||
# cache node
|
||||
self.nodes[path] = node
|
||||
|
||||
return self.nodes[path]
|
||||
|
||||
def get_largefile_node(self, path):
|
||||
id_, _ = self._get_id_for_path(path)
|
||||
pointer_spec = self._remote.is_large_file(id_)
|
||||
tree_id, _ = self._get_tree_id_for_path(path)
|
||||
pointer_spec = self._remote.is_large_file(tree_id)
|
||||
|
||||
if pointer_spec:
|
||||
# content of that file regular FileNode is the hash of largefile
|
||||
|
|
|
|||
|
|
@ -25,15 +25,14 @@ GIT repository module
|
|||
import logging
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
|
||||
from zope.cachedescriptors.property import Lazy as LazyProperty
|
||||
from zope.cachedescriptors.property import CachedProperty
|
||||
|
||||
from rhodecode.lib.compat import OrderedDict
|
||||
from rhodecode.lib.datelib import (
|
||||
utcdate_fromtimestamp, makedate, date_astimestamp)
|
||||
from rhodecode.lib.utils import safe_unicode, safe_str
|
||||
from rhodecode.lib.utils2 import CachedProperty
|
||||
from rhodecode.lib.vcs import connection, path as vcspath
|
||||
from rhodecode.lib.vcs.backends.base import (
|
||||
BaseRepository, CollectionGenerator, Config, MergeResponse,
|
||||
|
|
@ -71,9 +70,6 @@ class GitRepository(BaseRepository):
|
|||
# caches
|
||||
self._commit_ids = {}
|
||||
|
||||
# dependent that trigger re-computation of commit_ids
|
||||
self._commit_ids_ver = 0
|
||||
|
||||
@LazyProperty
|
||||
def _remote(self):
|
||||
return connection.Git(self.path, self.config, with_wire=self.with_wire)
|
||||
|
|
@ -86,7 +82,7 @@ class GitRepository(BaseRepository):
|
|||
def head(self):
|
||||
return self._remote.head()
|
||||
|
||||
@CachedProperty('_commit_ids_ver')
|
||||
@CachedProperty
|
||||
def commit_ids(self):
|
||||
"""
|
||||
Returns list of commit ids, in ascending order. Being lazy
|
||||
|
|
@ -190,12 +186,16 @@ class GitRepository(BaseRepository):
|
|||
except OSError as err:
|
||||
raise RepositoryError(err)
|
||||
|
||||
def _get_all_commit_ids(self, filters=None):
|
||||
def _get_all_commit_ids(self):
|
||||
return self._remote.get_all_commit_ids()
|
||||
|
||||
def _get_commit_ids(self, filters=None):
|
||||
# we must check if this repo is not empty, since later command
|
||||
# fails if it is. And it's cheaper to ask than throw the subprocess
|
||||
# errors
|
||||
|
||||
head = self._remote.head(show_exc=False)
|
||||
|
||||
if not head:
|
||||
return []
|
||||
|
||||
|
|
@ -208,7 +208,7 @@ class GitRepository(BaseRepository):
|
|||
if filters.get('until'):
|
||||
extra_filter.append('--until=%s' % (filters['until']))
|
||||
if filters.get('branch_name'):
|
||||
rev_filter = ['--tags']
|
||||
rev_filter = []
|
||||
extra_filter.append(filters['branch_name'])
|
||||
rev_filter.extend(extra_filter)
|
||||
|
||||
|
|
@ -233,6 +233,8 @@ class GitRepository(BaseRepository):
|
|||
|
||||
if commit_id_or_idx in (None, '', 'tip', 'HEAD', 'head', -1):
|
||||
return self.commit_ids[-1]
|
||||
commit_missing_err = "Commit {} does not exist for `{}`".format(
|
||||
*map(safe_str, [commit_id_or_idx, self.name]))
|
||||
|
||||
is_bstr = isinstance(commit_id_or_idx, (str, unicode))
|
||||
if ((is_bstr and commit_id_or_idx.isdigit() and len(commit_id_or_idx) < 12)
|
||||
|
|
@ -240,30 +242,15 @@ class GitRepository(BaseRepository):
|
|||
try:
|
||||
commit_id_or_idx = self.commit_ids[int(commit_id_or_idx)]
|
||||
except Exception:
|
||||
msg = "Commit {} does not exist for `{}`".format(commit_id_or_idx, self.name)
|
||||
raise CommitDoesNotExistError(msg)
|
||||
raise CommitDoesNotExistError(commit_missing_err)
|
||||
|
||||
elif is_bstr:
|
||||
# check full path ref, eg. refs/heads/master
|
||||
ref_id = self._refs.get(commit_id_or_idx)
|
||||
if ref_id:
|
||||
return ref_id
|
||||
|
||||
# check branch name
|
||||
branch_ids = self.branches.values()
|
||||
ref_id = self._refs.get('refs/heads/%s' % commit_id_or_idx)
|
||||
if ref_id:
|
||||
return ref_id
|
||||
|
||||
# check tag name
|
||||
ref_id = self._refs.get('refs/tags/%s' % commit_id_or_idx)
|
||||
if ref_id:
|
||||
return ref_id
|
||||
|
||||
if (not SHA_PATTERN.match(commit_id_or_idx) or
|
||||
commit_id_or_idx not in self.commit_ids):
|
||||
msg = "Commit {} does not exist for `{}`".format(commit_id_or_idx, self.name)
|
||||
raise CommitDoesNotExistError(msg)
|
||||
# Need to call remote to translate id for tagging scenario
|
||||
try:
|
||||
remote_data = self._remote.get_object(commit_id_or_idx)
|
||||
commit_id_or_idx = remote_data["commit_id"]
|
||||
except (CommitDoesNotExistError,):
|
||||
raise CommitDoesNotExistError(commit_missing_err)
|
||||
|
||||
# Ensure we return full id
|
||||
if not SHA_PATTERN.match(str(commit_id_or_idx)):
|
||||
|
|
@ -327,32 +314,31 @@ class GitRepository(BaseRepository):
|
|||
def _get_branches(self):
|
||||
return self._get_refs_entries(prefix='refs/heads/', strip_prefix=True)
|
||||
|
||||
@LazyProperty
|
||||
@CachedProperty
|
||||
def branches(self):
|
||||
return self._get_branches()
|
||||
|
||||
@LazyProperty
|
||||
@CachedProperty
|
||||
def branches_closed(self):
|
||||
return {}
|
||||
|
||||
@LazyProperty
|
||||
@CachedProperty
|
||||
def bookmarks(self):
|
||||
return {}
|
||||
|
||||
@LazyProperty
|
||||
@CachedProperty
|
||||
def branches_all(self):
|
||||
all_branches = {}
|
||||
all_branches.update(self.branches)
|
||||
all_branches.update(self.branches_closed)
|
||||
return all_branches
|
||||
|
||||
@LazyProperty
|
||||
@CachedProperty
|
||||
def tags(self):
|
||||
return self._get_tags()
|
||||
|
||||
def _get_tags(self):
|
||||
return self._get_refs_entries(
|
||||
prefix='refs/tags/', strip_prefix=True, reverse=True)
|
||||
return self._get_refs_entries(prefix='refs/tags/', strip_prefix=True, reverse=True)
|
||||
|
||||
def tag(self, name, user, commit_id=None, message=None, date=None,
|
||||
**kwargs):
|
||||
|
|
@ -368,15 +354,17 @@ class GitRepository(BaseRepository):
|
|||
|
||||
:raises TagAlreadyExistError: if tag with same name already exists
|
||||
"""
|
||||
print self._refs
|
||||
if name in self.tags:
|
||||
raise TagAlreadyExistError("Tag %s already exists" % name)
|
||||
commit = self.get_commit(commit_id=commit_id)
|
||||
message = message or "Added tag %s for commit %s" % (
|
||||
name, commit.raw_id)
|
||||
self._remote.set_refs('refs/tags/%s' % name, commit._commit['id'])
|
||||
message = message or "Added tag %s for commit %s" % (name, commit.raw_id)
|
||||
|
||||
self._remote.set_refs('refs/tags/%s' % name, commit.raw_id)
|
||||
|
||||
self._invalidate_prop_cache('tags')
|
||||
self._invalidate_prop_cache('_refs')
|
||||
|
||||
self._refs = self._get_refs()
|
||||
self.tags = self._get_tags()
|
||||
return commit
|
||||
|
||||
def remove_tag(self, name, user, message=None, date=None):
|
||||
|
|
@ -392,19 +380,15 @@ class GitRepository(BaseRepository):
|
|||
"""
|
||||
if name not in self.tags:
|
||||
raise TagDoesNotExistError("Tag %s does not exist" % name)
|
||||
tagpath = vcspath.join(
|
||||
self._remote.get_refs_path(), 'refs', 'tags', name)
|
||||
try:
|
||||
os.remove(tagpath)
|
||||
self._refs = self._get_refs()
|
||||
self.tags = self._get_tags()
|
||||
except OSError as e:
|
||||
raise RepositoryError(e.strerror)
|
||||
|
||||
self._remote.tag_remove(name)
|
||||
self._invalidate_prop_cache('tags')
|
||||
self._invalidate_prop_cache('_refs')
|
||||
|
||||
def _get_refs(self):
|
||||
return self._remote.get_refs()
|
||||
|
||||
@LazyProperty
|
||||
@CachedProperty
|
||||
def _refs(self):
|
||||
return self._get_refs()
|
||||
|
||||
|
|
@ -455,18 +439,13 @@ class GitRepository(BaseRepository):
|
|||
else:
|
||||
commit_id = "tip"
|
||||
|
||||
commit_id = self._lookup_commit(commit_id)
|
||||
remote_idx = None
|
||||
if translate_tag:
|
||||
# Need to call remote to translate id for tagging scenario
|
||||
remote_data = self._remote.get_object(commit_id)
|
||||
commit_id = remote_data["commit_id"]
|
||||
remote_idx = remote_data["idx"]
|
||||
commit_id = self._lookup_commit(commit_id)
|
||||
|
||||
try:
|
||||
idx = self._commit_ids[commit_id]
|
||||
except KeyError:
|
||||
idx = remote_idx or 0
|
||||
idx = -1
|
||||
|
||||
return GitCommit(self, commit_id, idx, pre_load=pre_load)
|
||||
|
||||
|
|
@ -539,14 +518,8 @@ class GitRepository(BaseRepository):
|
|||
'start': start_pos,
|
||||
'end': end_pos,
|
||||
}
|
||||
commit_ids = self._get_all_commit_ids(filters=revfilters)
|
||||
commit_ids = self._get_commit_ids(filters=revfilters)
|
||||
|
||||
# pure python stuff, it's slow due to walker walking whole repo
|
||||
# def get_revs(walker):
|
||||
# for walker_entry in walker:
|
||||
# yield walker_entry.commit.id
|
||||
# revfilters = {}
|
||||
# commit_ids = list(reversed(list(get_revs(self._repo.get_walker(**revfilters)))))
|
||||
else:
|
||||
commit_ids = self.commit_ids
|
||||
|
||||
|
|
@ -613,8 +586,11 @@ class GitRepository(BaseRepository):
|
|||
commit = commit.parents[0]
|
||||
self._remote.set_refs('refs/heads/%s' % branch_name, commit.raw_id)
|
||||
|
||||
self._commit_ids_ver = time.time()
|
||||
# we updated _commit_ids_ver so accessing self.commit_ids will re-compute it
|
||||
# clear cached properties
|
||||
self._invalidate_prop_cache('commit_ids')
|
||||
self._invalidate_prop_cache('_refs')
|
||||
self._invalidate_prop_cache('branches')
|
||||
|
||||
return len(self.commit_ids)
|
||||
|
||||
def get_common_ancestor(self, commit_id1, commit_id2, repo2):
|
||||
|
|
@ -697,9 +673,11 @@ class GitRepository(BaseRepository):
|
|||
|
||||
def set_refs(self, ref_name, commit_id):
|
||||
self._remote.set_refs(ref_name, commit_id)
|
||||
self._invalidate_prop_cache('_refs')
|
||||
|
||||
def remove_ref(self, ref_name):
|
||||
self._remote.remove_ref(ref_name)
|
||||
self._invalidate_prop_cache('_refs')
|
||||
|
||||
def _update_server_info(self):
|
||||
"""
|
||||
|
|
@ -744,6 +722,12 @@ class GitRepository(BaseRepository):
|
|||
cmd.append(branch_name)
|
||||
self.run_git_command(cmd, fail_on_stderr=False)
|
||||
|
||||
def _create_branch(self, branch_name, commit_id):
|
||||
"""
|
||||
creates a branch in a GIT repo
|
||||
"""
|
||||
self._remote.create_branch(branch_name, commit_id)
|
||||
|
||||
def _identify(self):
|
||||
"""
|
||||
Return the current state of the working directory.
|
||||
|
|
|
|||
|
|
@ -299,10 +299,11 @@ class MercurialCommit(base.BaseCommit):
|
|||
loc = vals[0]
|
||||
commit = vals[1]
|
||||
dirnodes.append(SubModuleNode(k, url=loc, commit=commit, alias=alias))
|
||||
|
||||
nodes = dirnodes + filenodes
|
||||
# cache nodes
|
||||
for node in nodes:
|
||||
self.nodes[node.path] = node
|
||||
if node.path not in self.nodes:
|
||||
self.nodes[node.path] = node
|
||||
nodes.sort()
|
||||
|
||||
return nodes
|
||||
|
|
|
|||
|
|
@ -24,16 +24,15 @@ HG repository module
|
|||
import os
|
||||
import logging
|
||||
import binascii
|
||||
import time
|
||||
import urllib
|
||||
|
||||
from zope.cachedescriptors.property import Lazy as LazyProperty
|
||||
from zope.cachedescriptors.property import CachedProperty
|
||||
|
||||
from rhodecode.lib.compat import OrderedDict
|
||||
from rhodecode.lib.datelib import (
|
||||
date_to_timestamp_plus_offset, utcdate_fromtimestamp, makedate)
|
||||
from rhodecode.lib.utils import safe_unicode, safe_str
|
||||
from rhodecode.lib.utils2 import CachedProperty
|
||||
from rhodecode.lib.vcs import connection, exceptions
|
||||
from rhodecode.lib.vcs.backends.base import (
|
||||
BaseRepository, CollectionGenerator, Config, MergeResponse,
|
||||
|
|
@ -87,14 +86,11 @@ class MercurialRepository(BaseRepository):
|
|||
# caches
|
||||
self._commit_ids = {}
|
||||
|
||||
# dependent that trigger re-computation of commit_ids
|
||||
self._commit_ids_ver = 0
|
||||
|
||||
@LazyProperty
|
||||
def _remote(self):
|
||||
return connection.Hg(self.path, self.config, with_wire=self.with_wire)
|
||||
|
||||
@CachedProperty('_commit_ids_ver')
|
||||
@CachedProperty
|
||||
def commit_ids(self):
|
||||
"""
|
||||
Returns list of commit ids, in ascending order. Being lazy
|
||||
|
|
@ -108,15 +104,15 @@ class MercurialRepository(BaseRepository):
|
|||
self._commit_ids = dict((commit_id, index)
|
||||
for index, commit_id in enumerate(commit_ids))
|
||||
|
||||
@LazyProperty
|
||||
@CachedProperty
|
||||
def branches(self):
|
||||
return self._get_branches()
|
||||
|
||||
@LazyProperty
|
||||
@CachedProperty
|
||||
def branches_closed(self):
|
||||
return self._get_branches(active=False, closed=True)
|
||||
|
||||
@LazyProperty
|
||||
@CachedProperty
|
||||
def branches_all(self):
|
||||
all_branches = {}
|
||||
all_branches.update(self.branches)
|
||||
|
|
@ -143,7 +139,7 @@ class MercurialRepository(BaseRepository):
|
|||
|
||||
return OrderedDict(sorted(_branches, key=get_name, reverse=False))
|
||||
|
||||
@LazyProperty
|
||||
@CachedProperty
|
||||
def tags(self):
|
||||
"""
|
||||
Gets tags for this repository
|
||||
|
|
@ -276,8 +272,9 @@ class MercurialRepository(BaseRepository):
|
|||
self._remote.strip(commit_id, update=False, backup="none")
|
||||
|
||||
self._remote.invalidate_vcs_cache()
|
||||
self._commit_ids_ver = time.time()
|
||||
# we updated _commit_ids_ver so accessing self.commit_ids will re-compute it
|
||||
# clear cache
|
||||
self._invalidate_prop_cache('commit_ids')
|
||||
|
||||
return len(self.commit_ids)
|
||||
|
||||
def verify(self):
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@ import os
|
|||
import urllib
|
||||
|
||||
from zope.cachedescriptors.property import Lazy as LazyProperty
|
||||
from zope.cachedescriptors.property import CachedProperty
|
||||
|
||||
from rhodecode.lib.compat import OrderedDict
|
||||
from rhodecode.lib.datelib import date_astimestamp
|
||||
from rhodecode.lib.utils import safe_str, safe_unicode
|
||||
from rhodecode.lib.utils2 import CachedProperty
|
||||
from rhodecode.lib.vcs import connection, path as vcspath
|
||||
from rhodecode.lib.vcs.backends import base
|
||||
from rhodecode.lib.vcs.backends.svn.commit import (
|
||||
|
|
@ -76,8 +76,9 @@ class SubversionRepository(base.BaseRepository):
|
|||
|
||||
self._init_repo(create, src_url)
|
||||
|
||||
# dependent that trigger re-computation of commit_ids
|
||||
self._commit_ids_ver = 0
|
||||
# caches
|
||||
self._commit_ids = {}
|
||||
|
||||
|
||||
@LazyProperty
|
||||
def _remote(self):
|
||||
|
|
@ -97,7 +98,7 @@ class SubversionRepository(base.BaseRepository):
|
|||
else:
|
||||
self._check_path()
|
||||
|
||||
@CachedProperty('_commit_ids_ver')
|
||||
@CachedProperty
|
||||
def commit_ids(self):
|
||||
head = self._remote.lookup(None)
|
||||
return [str(r) for r in xrange(1, head + 1)]
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class TestGitRepository(object):
|
|||
@pytest.fixture(autouse=True)
|
||||
def prepare(self, request, baseapp):
|
||||
self.repo = GitRepository(TEST_GIT_REPO, bare=True)
|
||||
self.repo.count()
|
||||
|
||||
def get_clone_repo(self, tmp_path_factory):
|
||||
"""
|
||||
|
|
@ -1242,7 +1243,7 @@ class TestGetSubmoduleUrl(object):
|
|||
commit = GitCommit(repository=repository, raw_id='abcdef12', idx=1)
|
||||
submodule_url = 'https://code.rhodecode.com/dulwich'
|
||||
get_id_patch = mock.patch.object(
|
||||
commit, '_get_id_for_path', return_value=(1, 'link'))
|
||||
commit, '_get_tree_id_for_path', return_value=(1, 'link'))
|
||||
get_submodule_patch = mock.patch.object(
|
||||
commit, '_get_submodule_url', return_value=submodule_url)
|
||||
|
||||
|
|
@ -1262,7 +1263,7 @@ class TestGetSubmoduleUrl(object):
|
|||
commit = GitCommit(repository=repository, raw_id='abcdef12', idx=1)
|
||||
submodule_url = 'https://code.rhodecode.com/dulwich'
|
||||
get_id_patch = mock.patch.object(
|
||||
commit, '_get_id_for_path', return_value=(1, 'tree'))
|
||||
commit, '_get_tree_id_for_path', return_value=(1, 'tree'))
|
||||
get_submodule_patch = mock.patch.object(
|
||||
commit, '_get_submodule_url', return_value=submodule_url)
|
||||
|
||||
|
|
|
|||
|
|
@ -88,8 +88,6 @@ class TestInMemoryCommit(BackendTestMixin):
|
|||
|
||||
@pytest.mark.backends("git")
|
||||
def test_add_on_branch_git(self, nodes):
|
||||
self.repo._checkout('stable', create=True)
|
||||
|
||||
for node in nodes:
|
||||
self.imc.add(node)
|
||||
self.commit(branch=u'stable')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue