@@ -4,49 +4,49 @@
~~~~~~~~~~~~~~~~~~
RhodeCode, a web based repository management based on pylons
versioning implementation: http://semver.org/
:created_on: Apr 9, 2010
:author: marcink
:copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
:license: GPLv3, see COPYING for more details.
"""
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import platform
VERSION = (1, 2, 4)
VERSION = (1, 2, 5)
__version__ = '.'.join((str(each) for each in VERSION[:4]))
__dbversion__ = 3 # defines current db version for migrations
__platform__ = platform.system()
__license__ = 'GPLv3'
PLATFORM_WIN = ('Windows')
PLATFORM_OTHERS = ('Linux', 'Darwin', 'FreeBSD', 'OpenBSD', 'SunOS')
requirements = [
"Pylons==1.0.0",
"Beaker==1.5.4",
"WebHelpers>=1.2",
"formencode==1.2.4",
"SQLAlchemy==0.7.4",
"Mako==0.5.0",
"pygments>=1.4",
"mercurial>=2.0,<2.1",
"whoosh<1.8",
"celery>=2.2.5,<2.3",
"babel",
"python-dateutil>=1.5.0,<2.0.0",
"dulwich>=0.8.0,<0.9.0",
"vcs==0.2.2",
"webob==1.0.8"
# -*- coding: utf-8 -*-
rhodecode.lib.celerylib.__init__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
celery libs for RhodeCode
:created_on: Nov 27, 2010
:copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
import os
import sys
import socket
import traceback
import logging
from os.path import dirname as dn, join as jn
from pylons import config
from hashlib import md5
from decorator import decorator
from vcs.utils.lazy import LazyProperty
from rhodecode.lib import str2bool, safe_str
from rhodecode.lib.pidlock import DaemonLock, LockHeld
from rhodecode.model import init_model
from rhodecode.model import meta
from rhodecode.model.db import Statistics, Repository, User
from sqlalchemy import engine_from_config
from celery.messaging import establish_connection
log = logging.getLogger(__name__)
try:
CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
except KeyError:
CELERY_ON = False
class ResultWrapper(object):
def __init__(self, task):
self.task = task
@LazyProperty
def result(self):
return self.task
def run_task(task, *args, **kwargs):
if CELERY_ON:
t = task.apply_async(args=args, kwargs=kwargs)
log.info('running task %s:%s', t.task_id, task)
return t
@@ -86,24 +90,44 @@ def __get_lockkey(func, *fargs, **fkwarg
func_name = str(func.__name__) if hasattr(func, '__name__') else str(func)
lockkey = 'task_%s.lock' % \
md5(func_name + '-' + '-'.join(map(safe_str, params))).hexdigest()
return lockkey
def locked_task(func):
def __wrapper(func, *fargs, **fkwargs):
lockkey = __get_lockkey(func, *fargs, **fkwargs)
lockkey_path = config['here']
log.info('running task with lockkey %s', lockkey)
l = DaemonLock(file_=jn(lockkey_path, lockkey))
ret = func(*fargs, **fkwargs)
l.release()
return ret
except LockHeld:
log.info('LockHeld')
return 'Task with key %s already running' % lockkey
return decorator(__wrapper, func)
def get_session():
engine = engine_from_config(config, 'sqlalchemy.db1.')
init_model(engine)
sa = meta.Session
return sa
def dbsession(func):
finally:
meta.Session.remove()
rhodecode.lib.celerylib.tasks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RhodeCode task modules, containing all task that suppose to be run
by celery daemon
:created_on: Oct 6, 2010
from celery.decorators import task
from time import mktime
from operator import itemgetter
from string import lower
from pylons import config, url
from pylons.i18n.translation import _
from rhodecode.lib import LANGUAGES_EXTENSIONS_MAP, safe_str
from rhodecode.lib.celerylib import run_task, locked_task, str2bool, \
__get_lockkey, LockHeld, DaemonLock
__get_lockkey, LockHeld, DaemonLock, get_session, dbsession
from rhodecode.lib.helpers import person
from rhodecode.lib.smtp_mailer import SmtpMailer
from rhodecode.lib.utils import add_cache
from rhodecode.lib.compat import json, OrderedDict
from rhodecode.model.db import RhodeCodeUi, Statistics, Repository, User
from vcs.backends import get_repo
from vcs import get_backend
add_cache(config)
__all__ = ['whoosh_index', 'get_commits_stats',
'reset_user_password', 'send_email']
sa = meta.Session()
def get_repos_path():
sa = get_session()
q = sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
return q.ui_value
@task(ignore_result=True)
@locked_task
@dbsession
def whoosh_index(repo_location, full_index):
#log = whoosh_index.get_logger()
from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
index_location = config['index_dir']
WhooshIndexingDaemon(index_location=index_location,
repo_location=repo_location, sa=get_session())\
.run(full_index=full_index)
def get_commits_stats(repo_name, ts_min_y, ts_max_y):
log = get_commits_stats.get_logger()
except:
lockkey = __get_lockkey('get_commits_stats', repo_name, ts_min_y,
ts_max_y)
lock = l = DaemonLock(file_=jn(lockkey_path, lockkey))
# for js data compatibilty cleans the key for person from '
akc = lambda k: person(k).replace('"', "")
co_day_auth_aggr = {}
commits_by_day_aggregate = {}
repos_path = get_repos_path()
repo = get_repo(safe_str(os.path.join(repos_path, repo_name)))
repo_size = repo.count()
# return if repo have no revisions
@@ -227,178 +217,179 @@ def get_commits_stats(repo_name, ts_min_
stats.repository = dbrepo
stats.stat_on_revision = last_cs.revision if last_cs else 0
sa.add(stats)
sa.commit()
log.error(traceback.format_exc())
sa.rollback()
lock.release()
return False
# final release
# execute another task if celery is enabled
if len(repo.revisions) > 1 and CELERY_ON:
run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
return True
def send_password_link(user_email):
log = reset_user_password.get_logger()
from rhodecode.lib import auth
from rhodecode.model.db import User
user = sa.query(User).filter(User.email == user_email).scalar()
if user:
link = url('reset_password_confirmation', key=user.api_key,
qualified=True)
tmpl = """
Hello %s
We received a request to create a new password for your account.
You can generate it by clicking following URL:
%s
If you didn't request new password please ignore this email.
run_task(send_email, user_email,
"RhodeCode password reset link",
tmpl % (user.short_contact, link))
log.info('send new password mail to %s', user_email)
log.error('Failed to update user password')
def reset_user_password(user_email):
new_passwd = auth.PasswordGenerator().gen_password(8,
auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
user.password = auth.get_crypt_password(new_passwd)
user.api_key = auth.generate_api_key(user.username)
sa.add(user)
log.info('change password for %s', user_email)
if new_passwd is None:
raise Exception('unable to generate new password')
"Your new RhodeCode password",
'Your new RhodeCode password:%s' % (new_passwd))
def send_email(recipients, subject, body):
Sends an email with defined parameters from the .ini files.
:param recipients: list of recipients, it this is empty the defined email
address from field 'email_to' is used instead
:param subject: subject of the mail
:param body: body of the mail
log = send_email.get_logger()
email_config = config
if not recipients:
# if recipients are not defined we send to email_config + all admins
admins = [
u.email for u in sa.query(User).filter(User.admin==True).all()
]
recipients = [email_config.get('email_to')] + admins
mail_from = email_config.get('app_email_from')
user = email_config.get('smtp_username')
passwd = email_config.get('smtp_password')
mail_server = email_config.get('smtp_server')
mail_port = email_config.get('smtp_port')
tls = str2bool(email_config.get('smtp_use_tls'))
ssl = str2bool(email_config.get('smtp_use_ssl'))
debug = str2bool(config.get('debug'))
smtp_auth = email_config.get('smtp_auth')
m = SmtpMailer(mail_from, user, passwd, mail_server,smtp_auth,
mail_port, ssl, tls, debug=debug)
m.send(recipients, subject, body)
log.error('Mail sending failed')
def create_repo_fork(form_data, cur_user):
from rhodecode.model.repo import RepoModel
log = create_repo_fork.get_logger()
repo_model = RepoModel(get_session())
repo_model.create(form_data, cur_user, just_db=True, fork=True)
repo_name = form_data['repo_name']
repo_path = os.path.join(repos_path, repo_name)
repo_fork_path = os.path.join(repos_path, form_data['fork_name'])
alias = form_data['repo_type']
log.info('creating repo fork %s as %s', repo_name, repo_path)
backend = get_backend(alias)
backend(str(repo_fork_path), create=True, src_url=str(repo_path))
def __get_codes_stats(repo_name):
tip = repo.get_changeset()
code_stats = {}
Status change: