Mercurial > public > src > rhodecode
changeset 552:c2627a73e8ec demo
merged with default branch
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Mon, 27 Sep 2010 02:18:25 +0200 |
parents | b5e1a66b4aac (current diff) d5efb83590ef (diff) |
children | d6a88bf3d3e6 |
files | hg_app_daemon hg_app_daemon2 |
diffstat | 18 files changed, 605 insertions(+), 240 deletions(-) [+] |
line wrap: on
line diff
--- a/celeryconfig.py Thu Sep 23 01:24:57 2010 +0200 +++ b/celeryconfig.py Mon Sep 27 02:18:25 2010 +0200 @@ -36,7 +36,7 @@ CELERYD_CONCURRENCY = 2 # CELERYD_LOG_FILE = "celeryd.log" CELERYD_LOG_LEVEL = "DEBUG" -CELERYD_MAX_TASKS_PER_CHILD = 1 +CELERYD_MAX_TASKS_PER_CHILD = 3 #Tasks will never be sent to the queue, but executed locally instead. CELERY_ALWAYS_EAGER = False
--- a/hg_app_daemon Thu Sep 23 01:24:57 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -#!/sbin/runscript -######################################## -#### THIS IS AN GENTOO INIT.D SCRIPT#### -######################################## - -APP_NAME="hg_app" -APP_HOMEDIR="marcink/python_workspace" -APP_PATH="/home/$APP_HOMEDIR/$APP_NAME" - -CONF_NAME="production.ini" - -PID_PATH="$APP_PATH/$APP_NAME.pid" -LOG_PATH="$APP_PATH/$APP_NAME.log" - -PYTHON_PATH="/home/$APP_HOMEDIR/v-env" - -RUN_AS="marcink" - -DAEMON="$PYTHON_PATH/bin/paster" - -DAEMON_OPTS="serve --daemon \ ---user=$RUN_AS \ ---group=$RUN_AS \ ---pid-file=$PID_PATH \ ---log-file=$LOG_PATH $APP_PATH/$CONF_NAME" - -#extra options -opts="${opts} restartdelay" - -depend() { - need nginx -} - -start() { - ebegin "Starting $APP_NAME" - start-stop-daemon -d $APP_PATH -e PYTHON_EGG_CACHE="/tmp" \ - --start --quiet \ - --pidfile $PID_PATH \ - --user $RUN_AS \ - --exec $DAEMON -- $DAEMON_OPTS - eend $? -} - -stop() { - ebegin "Stopping $APP_NAME" - start-stop-daemon -d $APP_PATH \ - --stop --quiet \ - --pidfile $PID_PATH || echo "$APP_NAME - Not running!" - if [ -f $PID_PATH ]; then - rm $PID_PATH - fi - eend $? -} - -restartdelay() { - #stop() - echo "sleep3" - sleep 3 - - #start() -}
--- a/hg_app_daemon2 Thu Sep 23 01:24:57 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -#!/bin/sh -e -######################################## -#### THIS IS AN DEBIAN INIT.D SCRIPT#### -######################################## - -### BEGIN INIT INFO -# Provides: hg-app -# Required-Start: $all -# Required-Stop: $all -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: starts instance of hg-app -# Description: starts instance of hg-app using start-stop-daemon -### END INIT INFO - -APP_NAME="hg_app" -APP_HOMEDIR="marcink/python_workspace" -APP_PATH="/home/$APP_HOMEDIR/$APP_NAME" - -CONF_NAME="production.ini" - -PID_PATH="$APP_PATH/$APP_NAME.pid" -LOG_PATH="$APP_PATH/$APP_NAME.log" - -PYTHON_PATH="/home/$APP_HOMEDIR/v-env" - -RUN_AS="marcink" - -DAEMON="$PYTHON_PATH/bin/paster" - -DAEMON_OPTS="serve --daemon \ ---user=$RUN_AS \ ---group=$RUN_AS \ ---pid-file=$PID_PATH \ ---log-file=$LOG_PATH $APP_PATH/$CONF_NAME" - - -case "$1" in - start) - echo "Starting $APP_NAME" - start-stop-daemon -d $APP_PATH -e PYTHON_EGG_CACHE="/tmp" \ - --start --quiet \ - --pidfile $PID_PATH \ - --user $RUN_AS \ - --exec $DAEMON -- $DAEMON_OPTS - ;; - stop) - echo "Stopping $APP_NAME" - start-stop-daemon -d $APP_PATH \ - --stop --quiet \ - --pidfile $PID_PATH || echo "$APP_NAME - Not running!" - if [ -f $PID_PATH ]; then - rm $PID_PATH - fi - ;; - restart) - echo "Restarting $APP_NAME" - ### stop ### - echo "Stopping $APP_NAME" - start-stop-daemon -d $APP_PATH \ - --stop --quiet \ - --pidfile $PID_PATH || echo "$APP_NAME - Not running!" - if [ -f $PID_PATH ]; then - rm $PID_PATH - fi - ### start ### - echo "Starting $APP_NAME" - start-stop-daemon -d $APP_PATH -e PYTHON_EGG_CACHE="/tmp" \ - --start --quiet \ - --pidfile $PID_PATH \ - --user $RUN_AS \ - --exec $DAEMON -- $DAEMON_OPTS - ;; - *) - echo "Usage: $0 {start|stop|restart}" - exit 1 -esac \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/init.d/celeryd Mon Sep 27 02:18:25 2010 +0200 @@ -0,0 +1,224 @@ +#!/bin/sh -e +# ============================================ +# celeryd - Starts the Celery worker daemon. +# ============================================ +# +# :Usage: /etc/init.d/celeryd {start|stop|force-reload|restart|try-restart|status} +# +# :Configuration file: /etc/default/celeryd +# +# To configure celeryd you probably need to tell it where to chdir. +# +# EXAMPLE CONFIGURATION +# ===================== +# +# this is an example configuration for a Python project: +# +# /etc/default/celeryd: +# +# # Where to chdir at start. +# CELERYD_CHDIR="/opt/Myproject/" +# +# # Extra arguments to celeryd +# CELERYD_OPTS="--time-limit 300" +# +# # Name of the celery config module.# +# CELERY_CONFIG_MODULE="celeryconfig" +# +# EXAMPLE DJANGO CONFIGURATION +# ============================ +# +# # Where the Django project is. +# CELERYD_CHDIR="/opt/Project/" +# +# # Name of the projects settings module. +# DJANGO_SETTINGS_MODULE="settings" +# +# # Path to celeryd +# CELERYD="/opt/Project/manage.py celeryd" +# +# AVAILABLE OPTIONS +# ================= +# +# * CELERYD_OPTS +# Additional arguments to celeryd, see ``celeryd --help`` for a list. +# +# * CELERYD_CHDIR +# Path to chdir at start. Default is to stay in the current directory. +# +# * CELERYD_PIDFILE +# Full path to the pidfile. Default is /var/run/celeryd.pid. +# +# * CELERYD_LOGFILE +# Full path to the celeryd logfile. Default is /var/log/celeryd.log +# +# * CELERYD_LOG_LEVEL +# Log level to use for celeryd. Default is INFO. +# +# * CELERYD +# Path to the celeryd program. Default is ``celeryd``. +# You can point this to an virtualenv, or even use manage.py for django. +# +# * CELERYD_USER +# User to run celeryd as. Default is current user. +# +# * CELERYD_GROUP +# Group to run celeryd as. Default is current user. + + +### BEGIN INIT INFO +# Provides: celeryd +# Required-Start: $network $local_fs $remote_fs +# Required-Stop: $network $local_fs $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: celery task worker daemon +### END INIT INFO + +set -e +CELERYD_CHDIR="/opt/Myproject/" +CELERYD_PID_FILE="/var/run/celeryd.pid" +CELERYD_LOG_FILE="/var/log/celeryd.log" +CELERYD_LOG_LEVEL="DEBUG" +DEFAULT_CELERYD="/home/v-env/celeryd" + +# /etc/init.d/ssh: start and stop the celery task worker daemon. + +if test -f /etc/default/celeryd; then + . /etc/default/celeryd +fi + +CELERYD=${CELERYD:-$DEFAULT_CELERYD} + +export CELERY_LOADER + +. /lib/lsb/init-functions + +CELERYD_OPTS="$CELERYD_OPTS -f $CELERYD_LOG_FILE -l $CELERYD_LOG_LEVEL" + +if [ -n "$2" ]; then + CELERYD_OPTS="$CELERYD_OPTS $2" +fi + +# Extra start-stop-daemon options, like user/group. +if [ -n "$CELERYD_USER" ]; then + DAEMON_OPTS="$DAEMON_OPTS --chuid $CELERYD_USER" +fi +if [ -n "$CELERYD_GROUP" ]; then + DAEMON_OPTS="$DAEMON_OPTS --group $CELERYD_GROUP" +fi + +if [ -n "$CELERYD_CHDIR" ]; then + DAEMON_OPTS="$DAEMON_OPTS --chdir $CELERYD_CHDIR" +fi + + +# Are we running from init? +run_by_init() { + ([ "$previous" ] && [ "$runlevel" ]) || [ "$runlevel" = S ] +} + + +check_dev_null() { + if [ ! -c /dev/null ]; then + if [ "$1" = log_end_msg ]; then + log_end_msg 1 || true + fi + if ! run_by_init; then + log_action_msg "/dev/null is not a character device!" + fi + exit 1 + fi +} + + +export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" + + +stop_worker () { + cmd="start-stop-daemon --stop \ + --quiet \ + $* \ + --pidfile $CELERYD_PID_FILE" + if $cmd; then + log_end_msg 0 + else + log_end_msg 1 + fi +} + +start_worker () { + cmd="start-stop-daemon --start $DAEMON_OPTS \ + --quiet \ + --oknodo \ + --background \ + --make-pidfile \ + $* \ + --pidfile $CELERYD_PID_FILE + --exec $CELERYD -- $CELERYD_OPTS" + if $cmd; then + log_end_msg 0 + else + log_end_msg 1 + fi +} + + + +case "$1" in + start) + check_dev_null + log_daemon_msg "Starting celery task worker server" "celeryd" + start_worker + ;; + stop) + log_daemon_msg "Stopping celery task worker server" "celeryd" + stop_worker --oknodo + ;; + + reload|force-reload) + echo "Use start+stop" + ;; + + restart) + log_daemon_msg "Restarting celery task worker server" "celeryd" + stop_worker --oknodo --retry 30 + check_dev_null log_end_msg + start_worker + ;; + + try-restart) + log_daemon_msg "Restarting celery task worker server" "celeryd" + set +e + stop_worker --retry 30 + RET="$?" + set -e + case $RET in + 0) + # old daemon stopped + check_dev_null log_end_msg + start_worker + ;; + 1) + # daemon not running + log_progress_msg "(not running)" + log_end_msg 0 + ;; + *) + # failed to stop + log_progress_msg "(failed to stop)" + log_end_msg 1 + ;; + esac + ;; + + status) + status_of_proc -p $CELERYD_PID_FILE $CELERYD celeryd && exit 0 || exit $? + ;; + + *) + log_action_msg "Usage: /etc/init.d/celeryd {start|stop|force-reload|restart|try-restart|status}" + exit 1 +esac + +exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/init.d/hg_app_daemon Mon Sep 27 02:18:25 2010 +0200 @@ -0,0 +1,61 @@ +#!/sbin/runscript +######################################## +#### THIS IS AN GENTOO INIT.D SCRIPT#### +######################################## + +APP_NAME="hg_app" +APP_HOMEDIR="marcink/python_workspace" +APP_PATH="/home/$APP_HOMEDIR/$APP_NAME" + +CONF_NAME="production.ini" + +PID_PATH="$APP_PATH/$APP_NAME.pid" +LOG_PATH="$APP_PATH/$APP_NAME.log" + +PYTHON_PATH="/home/$APP_HOMEDIR/v-env" + +RUN_AS="marcink" + +DAEMON="$PYTHON_PATH/bin/paster" + +DAEMON_OPTS="serve --daemon \ +--user=$RUN_AS \ +--group=$RUN_AS \ +--pid-file=$PID_PATH \ +--log-file=$LOG_PATH $APP_PATH/$CONF_NAME" + +#extra options +opts="${opts} restartdelay" + +depend() { + need nginx +} + +start() { + ebegin "Starting $APP_NAME" + start-stop-daemon -d $APP_PATH -e PYTHON_EGG_CACHE="/tmp" \ + --start --quiet \ + --pidfile $PID_PATH \ + --user $RUN_AS \ + --exec $DAEMON -- $DAEMON_OPTS + eend $? +} + +stop() { + ebegin "Stopping $APP_NAME" + start-stop-daemon -d $APP_PATH \ + --stop --quiet \ + --pidfile $PID_PATH || echo "$APP_NAME - Not running!" + if [ -f $PID_PATH ]; then + rm $PID_PATH + fi + eend $? +} + +restartdelay() { + #stop() + echo "sleep3" + sleep 3 + + #start() +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/init.d/hg_app_daemon2 Mon Sep 27 02:18:25 2010 +0200 @@ -0,0 +1,77 @@ +#!/bin/sh -e +######################################## +#### THIS IS AN DEBIAN INIT.D SCRIPT#### +######################################## + +### BEGIN INIT INFO +# Provides: hg-app +# Required-Start: $all +# Required-Stop: $all +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: starts instance of hg-app +# Description: starts instance of hg-app using start-stop-daemon +### END INIT INFO + +APP_NAME="hg_app" +APP_HOMEDIR="marcink/python_workspace" +APP_PATH="/home/$APP_HOMEDIR/$APP_NAME" + +CONF_NAME="production.ini" + +PID_PATH="$APP_PATH/$APP_NAME.pid" +LOG_PATH="$APP_PATH/$APP_NAME.log" + +PYTHON_PATH="/home/$APP_HOMEDIR/v-env" + +RUN_AS="marcink" + +DAEMON="$PYTHON_PATH/bin/paster" + +DAEMON_OPTS="serve --daemon \ +--user=$RUN_AS \ +--group=$RUN_AS \ +--pid-file=$PID_PATH \ +--log-file=$LOG_PATH $APP_PATH/$CONF_NAME" + + +case "$1" in + start) + echo "Starting $APP_NAME" + start-stop-daemon -d $APP_PATH -e PYTHON_EGG_CACHE="/tmp" \ + --start --quiet \ + --pidfile $PID_PATH \ + --user $RUN_AS \ + --exec $DAEMON -- $DAEMON_OPTS + ;; + stop) + echo "Stopping $APP_NAME" + start-stop-daemon -d $APP_PATH \ + --stop --quiet \ + --pidfile $PID_PATH || echo "$APP_NAME - Not running!" + if [ -f $PID_PATH ]; then + rm $PID_PATH + fi + ;; + restart) + echo "Restarting $APP_NAME" + ### stop ### + echo "Stopping $APP_NAME" + start-stop-daemon -d $APP_PATH \ + --stop --quiet \ + --pidfile $PID_PATH || echo "$APP_NAME - Not running!" + if [ -f $PID_PATH ]; then + rm $PID_PATH + fi + ### start ### + echo "Starting $APP_NAME" + start-stop-daemon -d $APP_PATH -e PYTHON_EGG_CACHE="/tmp" \ + --start --quiet \ + --pidfile $PID_PATH \ + --user $RUN_AS \ + --exec $DAEMON -- $DAEMON_OPTS + ;; + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac \ No newline at end of file
--- a/pylons_app/controllers/summary.py Thu Sep 23 01:24:57 2010 +0200 +++ b/pylons_app/controllers/summary.py Mon Sep 27 02:18:25 2010 +0200 @@ -35,7 +35,7 @@ from time import mktime import calendar import logging - +import json log = logging.getLogger(__name__) class SummaryController(BaseController): @@ -79,18 +79,25 @@ c.ts_min = ts_min_m c.ts_max = ts_max_y - stats = self.sa.query(Statistics)\ .filter(Statistics.repository == c.repo_info.dbrepo)\ .scalar() - - if stats: + + + if stats and stats.languages: + lang_stats = json.loads(stats.languages) c.commit_data = stats.commit_activity c.overview_data = stats.commit_activity_combined + c.trending_languages = json.dumps(OrderedDict( + sorted(lang_stats.items(), reverse=True, + key=lambda k: k[1])[:2] + ) + ) + print c.trending_languages else: - import json c.commit_data = json.dumps({}) c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 0] ]) + c.trending_languages = json.dumps({}) return render('summary/summary.html')
--- a/pylons_app/lib/celerylib/__init__.py Thu Sep 23 01:24:57 2010 +0200 +++ b/pylons_app/lib/celerylib/__init__.py Mon Sep 27 02:18:25 2010 +0200 @@ -31,31 +31,24 @@ return ResultWrapper(task(*args, **kwargs)) -class LockTask(object): - """LockTask decorator""" - - def __init__(self, func): - self.func = func - - def __call__(self, func): - return decorator(self.__wrapper, func) - - def __wrapper(self, func, *fargs, **fkwargs): - params = [] - params.extend(fargs) - params.extend(fkwargs.values()) +def locked_task(func): + def __wrapper(func, *fargs, **fkwargs): + params = list(fargs) + params.extend(['%s-%s' % ar for ar in fkwargs.items()]) + lockkey = 'task_%s' % \ - md5(str(self.func) + '-' + '-'.join(map(str, params))).hexdigest() + md5(str(func.__name__) + '-' + \ + '-'.join(map(str, params))).hexdigest() log.info('running task with lockkey %s', lockkey) try: l = DaemonLock(lockkey) - return func(*fargs, **fkwargs) + func(*fargs, **fkwargs) l.release() except LockHeld: log.info('LockHeld') return 'Task with key %s already running' % lockkey - + return decorator(__wrapper, func)
--- a/pylons_app/lib/celerylib/tasks.py Thu Sep 23 01:24:57 2010 +0200 +++ b/pylons_app/lib/celerylib/tasks.py Mon Sep 27 02:18:25 2010 +0200 @@ -1,16 +1,16 @@ from celery.decorators import task from celery.task.sets import subtask from celeryconfig import PYLONS_CONFIG as config +from operator import itemgetter from pylons.i18n.translation import _ -from pylons_app.lib.celerylib import run_task, LockTask +from pylons_app.lib.celerylib import run_task, locked_task from pylons_app.lib.helpers import person from pylons_app.lib.smtp_mailer import SmtpMailer from pylons_app.lib.utils import OrderedDict -from operator import itemgetter +from time import mktime from vcs.backends.hg import MercurialRepository -from time import mktime +import json import traceback -import json __all__ = ['whoosh_index', 'get_commits_stats', 'reset_user_password', 'send_email'] @@ -66,28 +66,19 @@ return settings @task +@locked_task def whoosh_index(repo_location, full_index): log = whoosh_index.get_logger() - from pylons_app.lib.pidlock import DaemonLock - from pylons_app.lib.indexers.daemon import WhooshIndexingDaemon, LockHeld - try: - l = DaemonLock() - WhooshIndexingDaemon(repo_location=repo_location)\ - .run(full_index=full_index) - l.release() - return 'Done' - except LockHeld: - log.info('LockHeld') - return 'LockHeld' - + from pylons_app.lib.indexers.daemon import WhooshIndexingDaemon + WhooshIndexingDaemon(repo_location=repo_location).run(full_index=full_index) @task -@LockTask('get_commits_stats') +@locked_task def get_commits_stats(repo_name, ts_min_y, ts_max_y): - author_key_cleaner = lambda k: person(k).replace('"', "") #for js data compatibilty - from pylons_app.model.db import Statistics, Repository log = get_commits_stats.get_logger() + author_key_cleaner = lambda k: person(k).replace('"', "") #for js data compatibilty + commits_by_day_author_aggregate = {} commits_by_day_aggregate = {} repos_path = get_hg_ui_settings()['paths_root_path'].replace('*', '') @@ -108,7 +99,7 @@ if cur_stats: last_rev = cur_stats.stat_on_revision - if last_rev == repo.revisions[-1]: + if last_rev == repo.revisions[-1] and len(repo.revisions) > 1: #pass silently without any work return True @@ -118,6 +109,7 @@ cur_stats.commit_activity_combined)) commits_by_day_author_aggregate = json.loads(cur_stats.commit_activity) + log.debug('starting parsing %s', parse_limit) for cnt, rev in enumerate(repo.revisions[last_rev:]): last_cs = cs = repo.get_changeset(rev) k = '%s-%s-%s' % (cs.date.timetuple()[0], cs.date.timetuple()[1], @@ -196,9 +188,16 @@ stats = cur_stats if cur_stats else Statistics() stats.commit_activity = json.dumps(commits_by_day_author_aggregate) stats.commit_activity_combined = json.dumps(overview_data) + + log.debug('last revison %s', last_rev) + leftovers = len(repo.revisions[last_rev:]) + log.debug('revisions to parse %s', leftovers) + + if last_rev == 0 or leftovers < parse_limit: + stats.languages = json.dumps(__get_codes_stats(repo_name)) + stats.repository = dbrepo stats.stat_on_revision = last_cs.revision - stats.languages = json.dumps({'_TOTAL_':0, '':0}) try: sa.add(stats) @@ -207,8 +206,8 @@ log.error(traceback.format_exc()) sa.rollback() return False - - run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y) + if len(repo.revisions) > 1: + run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y) return True @@ -268,3 +267,31 @@ log.error(traceback.format_exc()) return False return True + +def __get_codes_stats(repo_name): + LANGUAGES_EXTENSIONS = ['action', 'adp', 'ashx', 'asmx', 'aspx', 'asx', 'axd', 'c', + 'cfg', 'cfm', 'cpp', 'cs', 'diff', 'do', 'el', 'erl', + 'h', 'java', 'js', 'jsp', 'jspx', 'lisp', + 'lua', 'm', 'mako', 'ml', 'pas', 'patch', 'php', 'php3', + 'php4', 'phtml', 'pm', 'py', 'rb', 'rst', 's', 'sh', + 'tpl', 'txt', 'vim', 'wss', 'xhtml', 'xml', 'xsl', 'xslt', + 'yaws'] + repos_path = get_hg_ui_settings()['paths_root_path'].replace('*', '') + repo = MercurialRepository(repos_path + repo_name) + + code_stats = {} + for topnode, dirs, files in repo.walk('/', 'tip'): + for f in files: + k = f.mimetype + if f.extension in LANGUAGES_EXTENSIONS: + if code_stats.has_key(k): + code_stats[k] += 1 + else: + code_stats[k] = 1 + + return code_stats or {} + + + + +
--- a/pylons_app/lib/helpers.py Thu Sep 23 01:24:57 2010 +0200 +++ b/pylons_app/lib/helpers.py Mon Sep 27 02:18:25 2010 +0200 @@ -213,14 +213,23 @@ return literal('/'.join(url_l)) files_breadcrumbs = _FilesBreadCrumbs() +class CodeHtmlFormatter(HtmlFormatter): + def wrap(self, source, outfile): + return self._wrap_div(self._wrap_pre(self._wrap_code(source))) + + def _wrap_code(self, source): + for cnt, it in enumerate(source, 1): + i, t = it + t = '<div id="#S-%s">%s</div>' % (cnt, t) + yield i, t def pygmentize(filenode, **kwargs): """ pygmentize function using pygments @param filenode: """ return literal(code_highlight(filenode.content, - filenode.lexer, HtmlFormatter(**kwargs))) + filenode.lexer, CodeHtmlFormatter(**kwargs))) def pygmentize_annotation(filenode, **kwargs): """
--- a/pylons_app/lib/hooks.py Thu Sep 23 01:24:57 2010 +0200 +++ b/pylons_app/lib/hooks.py Mon Sep 27 02:18:25 2010 +0200 @@ -26,12 +26,13 @@ import sys import os from pylons_app.lib import helpers as h +from pylons_app.model import meta +from pylons_app.model.db import UserLog, User def repo_size(ui, repo, hooktype=None, **kwargs): if hooktype != 'changegroup': return False - size_hg, size_root = 0, 0 for path, dirs, files in os.walk(repo.root): if path.find('.hg') != -1: @@ -43,6 +44,35 @@ size_hg_f = h.format_byte_size(size_hg) size_root_f = h.format_byte_size(size_root) - size_total_f = h.format_byte_size(size_root + size_hg) + size_total_f = h.format_byte_size(size_root + size_hg) sys.stdout.write('Repository size .hg:%s repo:%s total:%s\n' \ % (size_hg_f, size_root_f, size_total_f)) + + user_action_mapper(ui, repo, hooktype, **kwargs) + +def user_action_mapper(ui, repo, hooktype=None, **kwargs): + """ + Maps user last push action to new changeset id, from mercurial + @param ui: + @param repo: + @param hooktype: + """ + + try: + sa = meta.Session + username = kwargs['url'].split(':')[-1] + user_log = sa.query(UserLog)\ + .filter(UserLog.user == sa.query(User)\ + .filter(User.username == username).one())\ + .order_by(UserLog.user_log_id.desc()).first() + + if not user_log.revision: + user_log.revision = str(repo['tip']) + sa.add(user_log) + sa.commit() + + except Exception, e: + sa.rollback() + raise + finally: + meta.Session.remove()
--- a/pylons_app/lib/middleware/simplehg.py Thu Sep 23 01:24:57 2010 +0200 +++ b/pylons_app/lib/middleware/simplehg.py Mon Sep 27 02:18:25 2010 +0200 @@ -121,7 +121,7 @@ return HTTPNotFound()(environ, start_response) try: app = wsgiapplication(self.__make_app) - except RepoError as e: + except RepoError, e: if str(e).find('not found') != -1: return HTTPNotFound()(environ, start_response) except Exception: @@ -195,7 +195,7 @@ sa.commit() log.info('Adding user %s, action %s on %s', user.username, action, repo) - except Exception as e: + except Exception, e: sa.rollback() log.error('could not log user action:%s', str(e)) finally:
--- a/pylons_app/lib/pidlock.py Thu Sep 23 01:24:57 2010 +0200 +++ b/pylons_app/lib/pidlock.py Mon Sep 27 02:18:25 2010 +0200 @@ -1,6 +1,8 @@ import os, time import sys from warnings import warn +from multiprocessing.util import Finalize +import errno class LockHeld(Exception):pass @@ -9,7 +11,7 @@ """daemon locking USAGE: try: - l = lock() + l = DaemonLock(desc='test lock') main() l.release() except LockHeld: @@ -27,57 +29,67 @@ self.held = False #run the lock automatically ! self.lock() - - def __del__(self): - if self.held: + self._finalize = Finalize(self, DaemonLock._on_finalize, + args=(self, debug), exitpriority=10) -# warn("use lock.release instead of del lock", -# category = DeprecationWarning, -# stacklevel = 2) - - # ensure the lock will be removed - self.release() + @staticmethod + def _on_finalize(lock, debug): + if lock.held: + if debug: + print 'leck held finilazing and running lock.release()' + lock.release() def lock(self): - """ - locking function, if lock is present it will raise LockHeld exception + """locking function, if lock is present it will raise LockHeld exception """ lockname = '%s' % (os.getpid()) - + if self.debug: + print 'running lock' self.trylock() self.makelock(lockname, self.pidfile) return True def trylock(self): running_pid = False + if self.debug: + print 'checking for already running process' try: pidfile = open(self.pidfile, "r") pidfile.seek(0) - running_pid = pidfile.readline() + running_pid = int(pidfile.readline()) + + pidfile.close() + if self.debug: print 'lock file present running_pid: %s, checking for execution'\ % running_pid # Now we check the PID from lock file matches to the current # process PID if running_pid: - if os.path.exists("/proc/%s" % running_pid): - print "You already have an instance of the program running" - print "It is running as process %s" % running_pid - raise LockHeld + try: + os.kill(running_pid, 0) + except OSError, exc: + if exc.errno in (errno.ESRCH, errno.EPERM): + print "Lock File is there but the program is not running" + print "Removing lock file for the: %s" % running_pid + self.release() + raise else: - print "Lock File is there but the program is not running" - print "Removing lock file for the: %s" % running_pid - self.release() + print "You already have an instance of the program running" + print "It is running as process %s" % running_pid + raise LockHeld() + except IOError, e: if e.errno != 2: raise - def release(self): + """releases the pid by removing the pidfile """ - releases the pid by removing the pidfile - """ + if self.debug: + print 'trying to release the pidlock' + if self.callbackfn: #execute callback function on release if self.debug: @@ -105,23 +117,3 @@ pidfile.write(lockname) pidfile.close self.held = True - - -def main(): - print 'func is running' - cnt = 20 - while 1: - print cnt - if cnt == 0: - break - time.sleep(1) - cnt -= 1 - - -if __name__ == "__main__": - try: - l = DaemonLock(desc='test lock') - main() - l.release() - except LockHeld: - sys.exit(1)
--- a/pylons_app/model/db.py Thu Sep 23 01:24:57 2010 +0200 +++ b/pylons_app/model/db.py Mon Sep 27 02:18:25 2010 +0200 @@ -70,7 +70,7 @@ repository = Column("repository", TEXT(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_name'), nullable=False, unique=None, default=None) action = Column("action", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) action_date = Column("action_date", DATETIME(timezone=False), nullable=True, unique=None, default=None) - + revision = Column('revision', TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) user = relation('User') class Repository(Base):
--- a/pylons_app/public/css/pygments.css Thu Sep 23 01:24:57 2010 +0200 +++ b/pylons_app/public/css/pygments.css Mon Sep 27 02:18:25 2010 +0200 @@ -22,10 +22,13 @@ margin-left:25px; font-weight: normal; } + div.codeblock .code-body table{ width: 0 !important; } - +div.code-body { + background-color: #FFFFFF; +} div.code-body pre .match{ background-color: #FAFFA6; } @@ -36,13 +39,10 @@ display: block; } - div.annotatediv{ margin-left:2px; margin-right:4px; } - - .code-highlight { padding: 0px; margin-top: 5px; @@ -55,7 +55,6 @@ } .linenos a { text-decoration: none; } - .code { display: block; } .code-highlight .hll { background-color: #ffffcc } .code-highlight .c { color: #408080; font-style: italic } /* Comment */
--- a/pylons_app/public/css/style.css Thu Sep 23 01:24:57 2010 +0200 +++ b/pylons_app/public/css/style.css Mon Sep 27 02:18:25 2010 +0200 @@ -2963,6 +2963,28 @@ /* ----------------------------------------------------------- SUMMARY ----------------------------------------------------------- */ +.trending_language_tbl, .trending_language_tbl td { + margin: 0px !important; + padding: 0px !important; + border: 0 !important; + +} +.trending_language{ + -moz-border-radius-bottomright:4px; + -moz-border-radius-topright:4px; + border-bottom-right-radius: 4px 4px; + border-top-right-radius: 4px 4px; + background-color:#336699; + color:#FFFFFF; + display:block; + min-width:20px; + max-width:400px; + padding:3px; + text-decoration:none; + height: 10px; + margin-bottom: 4px; + margin-left: 5px; +} #clone_url{ border: none;
--- a/pylons_app/templates/admin/admin_log.html Thu Sep 23 01:24:57 2010 +0200 +++ b/pylons_app/templates/admin/admin_log.html Mon Sep 27 02:18:25 2010 +0200 @@ -13,7 +13,14 @@ <tr class="parity${cnt%2}"> <td>${h.link_to(l.user.username,h.url('edit_user', id=l.user.user_id))}</td> <td>${h.link_to(l.repository,h.url('summary_home',repo_name=l.repository))}</td> - <td>${l.action}</td> + <td> + % if l.action == 'push' and l.revision: + ${h.link_to('%s - %s' % (l.action,l.revision), + h.url('changeset_home',repo_name=l.repository,revision=l.revision))} + %else: + ${l.action} + %endif + </td> <td>${l.action_date}</td> <td>${l.user_ip}</td> </tr>
--- a/pylons_app/templates/summary/summary.html Thu Sep 23 01:24:57 2010 +0200 +++ b/pylons_app/templates/summary/summary.html Mon Sep 27 02:18:25 2010 +0200 @@ -90,7 +90,62 @@ <input type="text" id="clone_url" readonly="readonly" value="hg clone ${c.clone_repo_url}" size="70"/> </div> </div> - + + <div class="field"> + <div class="label"> + <label>${_('Trending languages')}:</label> + </div> + <div class="input-short"> + <div id="lang_stats"> + + </div> + <script type="text/javascript"> + var data = ${c.trending_languages|n}; + var total = 0; + var no_data = true; + for (k in data){ + total += data[k]; + no_data = false; + } + var tbl = document.createElement('table'); + tbl.setAttribute('class','trending_language_tbl'); + for (k in data){ + var tr = document.createElement('tr'); + var percentage = Math.round((data[k]/total*100),2); + var value = data[k]; + var td1 = document.createElement('td'); + td1.width=150; + var trending_language_label = document.createElement('div'); + trending_language_label.innerHTML = k; + td1.appendChild(trending_language_label); + + var td2 = document.createElement('td'); + var trending_language = document.createElement('div'); + trending_language.title = k; + trending_language.innerHTML = "<b>"+value+" ${_('files')} - "+percentage+" %</b>"; + trending_language.setAttribute("class", 'trending_language'); + trending_language.style.width=percentage+"%"; + td2.appendChild(trending_language); + + tr.appendChild(td1); + tr.appendChild(td2); + tbl.appendChild(tr); + //YAHOO.util.Dom.get('lang_stats').appendChild(trending_language_label); + + } + if(no_data){ + var tr = document.createElement('tr'); + var td1 = document.createElement('td'); + td1.innerHTML = "${_('No data loaded yet...')}"; + tr.appendChild(td1); + tbl.appendChild(tr); + } + YAHOO.util.Dom.get('lang_stats').appendChild(tbl); + </script> + + </div> + </div> + <div class="field"> <div class="label"> <label>${_('Download')}:</label>