@@ -118,402 +118,404 @@ def action_logger(user, action, repo, ip
:param user: user that made this action, can be a unique username string or
object containing user_id attribute
:param action: action to log, should be on of predefined unique actions for
easy translations
:param repo: string name of repository or object containing repo_id,
that action was made on
:param ipaddr: optional ip address from what the action was made
:param sa: optional sqlalchemy session
"""
if not sa:
sa = meta.Session()
try:
if hasattr(user, 'user_id'):
user_obj = user
elif isinstance(user, basestring):
user_obj = User.get_by_username(user)
else:
raise Exception('You have to provide a user object or a username')
if hasattr(repo, 'repo_id'):
repo_obj = Repository.get(repo.repo_id)
repo_name = repo_obj.repo_name
elif isinstance(repo, basestring):
repo_name = repo.lstrip('/')
repo_obj = Repository.get_by_repo_name(repo_name)
repo_obj = None
repo_name = ''
user_log = UserLog()
user_log.user_id = user_obj.user_id
user_log.action = safe_unicode(action)
user_log.repository = repo_obj
user_log.repository_name = repo_name
user_log.action_date = datetime.datetime.now()
user_log.user_ip = ipaddr
sa.add(user_log)
log.info(
'Adding user %s, action %s on %s' % (user_obj, action,
safe_unicode(repo))
)
if commit:
sa.commit()
except:
log.error(traceback.format_exc())
raise
def get_repos(path, recursive=False):
Scans given path for repos and return (name,(type,path)) tuple
:param path: path to scan for repositories
:param recursive: recursive search and return names with subdirs in front
# remove ending slash for better results
path = path.rstrip(os.sep)
def _get_repos(p):
if not os.access(p, os.W_OK):
return
for dirpath in os.listdir(p):
if os.path.isfile(os.path.join(p, dirpath)):
continue
cur_path = os.path.join(p, dirpath)
scm_info = get_scm(cur_path)
yield scm_info[1].split(path, 1)[-1].lstrip(os.sep), scm_info
except VCSError:
if not recursive:
#check if this dir containts other repos for recursive scan
rec_path = os.path.join(p, dirpath)
if os.path.isdir(rec_path):
for inner_scm in _get_repos(rec_path):
yield inner_scm
return _get_repos(path)
def is_valid_repo(repo_name, base_path, scm=None):
Returns True if given path is a valid repository False otherwise.
If scm param is given also compare if given scm is the same as expected
from scm parameter
:param repo_name:
:param base_path:
:param scm:
:return True: if given path is a valid repository
full_path = os.path.join(safe_str(base_path), safe_str(repo_name))
scm_ = get_scm(full_path)
if scm:
return scm_[0] == scm
return True
return False
def is_valid_repos_group(repos_group_name, base_path):
Returns True if given path is a repos group False otherwise
full_path = os.path.join(safe_str(base_path), safe_str(repos_group_name))
# check if it's not a repo
if is_valid_repo(repos_group_name, base_path):
# we need to check bare git repos at higher level
# since we might match branches/hooks/info/objects or possible
# other things inside bare git repo
get_scm(os.path.dirname(full_path))
pass
# check if it's a valid path
if os.path.isdir(full_path):
def ask_ok(prompt, retries=4, complaint='Yes or no please!'):
while True:
ok = raw_input(prompt)
if ok in ('y', 'ye', 'yes'):
if ok in ('n', 'no', 'nop', 'nope'):
retries = retries - 1
if retries < 0:
raise IOError
print complaint
#propagated from mercurial documentation
ui_sections = ['alias', 'auth',
'decode/encode', 'defaults',
'diff', 'email',
'extensions', 'format',
'merge-patterns', 'merge-tools',
'hooks', 'http_proxy',
'smtp', 'patch',
'paths', 'profiling',
'server', 'trusted',
'ui', 'web', ]
def make_ui(read_from='file', path=None, checkpaths=True, clear_session=True):
A function that will read python rc files or database
and make an mercurial ui object from read options
:param path: path to mercurial config file
:param checkpaths: check the path
:param read_from: read from 'file' or 'db'
baseui = ui.ui()
# clean the baseui object
baseui._ocfg = config.config()
baseui._ucfg = config.config()
baseui._tcfg = config.config()
if read_from == 'file':
if not os.path.isfile(path):
log.debug('hgrc file is not present at %s, skipping...' % path)
log.debug('reading hgrc from %s' % path)
cfg = config.config()
cfg.read(path)
for section in ui_sections:
for k, v in cfg.items(section):
log.debug('settings ui from file[%s]%s:%s' % (section, k, v))
baseui.setconfig(section, k, v)
baseui.setconfig(safe_str(section), safe_str(k), safe_str(v))
elif read_from == 'db':
ret = sa.query(RhodeCodeUi)\
.options(FromCache("sql_cache_short", "get_hg_ui_settings"))\
.all()
hg_ui = ret
for ui_ in hg_ui:
if ui_.ui_active:
log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
ui_.ui_key, ui_.ui_value)
baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key),
safe_str(ui_.ui_value))
if ui_.ui_key == 'push_ssl':
# force set push_ssl requirement to False, rhodecode
# handles that
baseui.setconfig(ui_.ui_section, ui_.ui_key, False)
False)
if clear_session:
meta.Session.remove()
return baseui
def set_rhodecode_config(config):
Updates pylons config with new settings from database
:param config:
hgsettings = RhodeCodeSetting.get_app_settings()
for k, v in hgsettings.items():
config[k] = v
def invalidate_cache(cache_key, *args):
Puts cache invalidation task into db for
further global cache invalidation
from rhodecode.model.scm import ScmModel
if cache_key.startswith('get_repo_cached_'):
name = cache_key.split('get_repo_cached_')[-1]
ScmModel().mark_for_invalidation(name)
def map_groups(path):
Given a full path to a repository, create all nested groups that this
repo is inside. This function creates parent-child relationships between
groups and creates default perms for all new groups.
:param paths: full path to repository
groups = path.split(Repository.url_sep())
parent = None
group = None
# last element is repo in nested groups structure
groups = groups[:-1]
rgm = ReposGroupModel(sa)
for lvl, group_name in enumerate(groups):
group_name = '/'.join(groups[:lvl] + [group_name])
group = RepoGroup.get_by_group_name(group_name)
desc = '%s group' % group_name
# skip folders that are now removed repos
if REMOVED_REPO_PAT.match(group_name):
break
if group is None:
log.debug('creating group level: %s group_name: %s' % (lvl,
group_name))
group = RepoGroup(group_name, parent)
group.group_description = desc
sa.add(group)
rgm._create_default_perms(group)
sa.flush()
parent = group
return group
def repo2db_mapper(initial_repo_list, remove_obsolete=False,
install_git_hook=False):
maps all repos given in initial_repo_list, non existing repositories
are created, if remove_obsolete is True it also check for db entries
that are not in initial_repo_list and removes them.
:param initial_repo_list: list of repositories found by scanning methods
:param remove_obsolete: check for obsolete entries in database
:param install_git_hook: if this is True, also check and install githook
for a repo if missing
from rhodecode.model.repo import RepoModel
rm = RepoModel()
user = sa.query(User).filter(User.admin == True).first()
if user is None:
raise Exception('Missing administrative account!')
added = []
# # clear cache keys
# log.debug("Clearing cache keys now...")
# CacheInvalidation.clear_cache()
# sa.commit()
for name, repo in initial_repo_list.items():
group = map_groups(name)
db_repo = rm.get_by_repo_name(name)
# found repo that is on filesystem not in RhodeCode database
if not db_repo:
log.info('repository %s not found, creating now' % name)
added.append(name)
desc = (repo.description
if repo.description != 'unknown'
else '%s repository' % name)
new_repo = rm.create_repo(
repo_name=name,
repo_type=repo.alias,
description=desc,
repos_group=getattr(group, 'group_id', None),
owner=user,
just_db=True
# we added that repo just now, and make sure it has githook
# installed
if new_repo.repo_type == 'git':
ScmModel().install_git_hook(new_repo.scm_instance)
elif install_git_hook:
if db_repo.repo_type == 'git':
ScmModel().install_git_hook(db_repo.scm_instance)
# during starting install all cache keys for all repositories in the
# system, this will register all repos and multiple instances
key, _prefix, _org_key = CacheInvalidation._get_key(name)
log.debug("Creating a cache key for %s instance_id:`%s`" % (name, _prefix))
CacheInvalidation._get_or_create_key(key, _prefix, _org_key, commit=False)
removed = []
if remove_obsolete:
# remove from database those repositories that are not in the filesystem
for repo in sa.query(Repository).all():
if repo.repo_name not in initial_repo_list.keys():
log.debug("Removing non-existing repository found in db `%s`" %
repo.repo_name)
sa.delete(repo)
removed.append(repo.repo_name)
#don't hold further removals on error
sa.rollback()
return added, removed
# set cache regions for beaker so celery can utilise it
def add_cache(settings):
cache_settings = {'regions': None}
for key in settings.keys():
for prefix in ['beaker.cache.', 'cache.']:
if key.startswith(prefix):
name = key.split(prefix)[1].strip()
cache_settings[name] = settings[key].strip()
if cache_settings['regions']:
for region in cache_settings['regions'].split(','):
region = region.strip()
region_settings = {}
for key, value in cache_settings.items():
if key.startswith(region):
region_settings[key.split('.')[1]] = value
region_settings['expire'] = int(region_settings.get('expire',
60))
region_settings.setdefault('lock_dir',
cache_settings.get('lock_dir'))
region_settings.setdefault('data_dir',
cache_settings.get('data_dir'))
if 'type' not in region_settings:
region_settings['type'] = cache_settings.get('type',
'memory')
beaker.cache.cache_regions[region] = region_settings
def load_rcextensions(root_path):
import rhodecode
from rhodecode.config import conf
path = os.path.join(root_path, 'rcextensions', '__init__.py')
if os.path.isfile(path):
rcext = create_module('rc', path)
EXT = rhodecode.EXTENSIONS = rcext
log.debug('Found rcextensions now loading %s...' % rcext)
# Additional mappings that are not present in the pygments lexers
conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {}))
#OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present)
if getattr(EXT, 'INDEX_EXTENSIONS', []) != []:
log.debug('settings custom INDEX_EXTENSIONS')
conf.INDEX_EXTENSIONS = getattr(EXT, 'INDEX_EXTENSIONS', [])
#ADDITIONAL MAPPINGS
log.debug('adding extra into INDEX_EXTENSIONS')
Status change: