diff --git a/rhodecode/lib/hooks.py b/rhodecode/lib/hooks.py --- a/rhodecode/lib/hooks.py +++ b/rhodecode/lib/hooks.py @@ -34,6 +34,9 @@ from rhodecode.lib import helpers as h from rhodecode.lib.utils import action_logger from rhodecode.lib.vcs.backends.base import EmptyChangeset from rhodecode.lib.compat import json +from rhodecode.model.db import Repository, User +from rhodecode.lib.utils2 import safe_str +from rhodecode.lib.exceptions import HTTPLockedRC def _get_scm_size(alias, root_path): @@ -84,6 +87,59 @@ def repo_size(ui, repo, hooktype=None, * sys.stdout.write(msg) +def pre_push(ui, repo, **kwargs): + # pre push function, currently used to ban pushing when + # repository is locked + try: + rc_extras = json.loads(os.environ.get('RC_SCM_DATA', "{}")) + except: + rc_extras = {} + extras = dict(repo.ui.configitems('rhodecode_extras')) + + if 'username' in extras: + username = extras['username'] + repository = extras['repository'] + scm = extras['scm'] + locked_by = extras['locked_by'] + elif 'username' in rc_extras: + username = rc_extras['username'] + repository = rc_extras['repository'] + scm = rc_extras['scm'] + locked_by = rc_extras['locked_by'] + else: + raise Exception('Missing data in repo.ui and os.environ') + + usr = User.get_by_username(username) + + if locked_by[0] and usr.user_id != int(locked_by[0]): + raise HTTPLockedRC(username, repository) + + +def pre_pull(ui, repo, **kwargs): + # pre push function, currently used to ban pushing when + # repository is locked + try: + rc_extras = json.loads(os.environ.get('RC_SCM_DATA', "{}")) + except: + rc_extras = {} + extras = dict(repo.ui.configitems('rhodecode_extras')) + if 'username' in extras: + username = extras['username'] + repository = extras['repository'] + scm = extras['scm'] + locked_by = extras['locked_by'] + elif 'username' in rc_extras: + username = rc_extras['username'] + repository = rc_extras['repository'] + scm = rc_extras['scm'] + locked_by = rc_extras['locked_by'] + else: + raise Exception('Missing data in repo.ui and os.environ') + + if locked_by[0]: + raise HTTPLockedRC(username, repository) + + def log_pull_action(ui, repo, **kwargs): """ Logs user last pull action @@ -100,15 +156,17 @@ def log_pull_action(ui, repo, **kwargs): username = extras['username'] repository = extras['repository'] scm = extras['scm'] + make_lock = extras['make_lock'] elif 'username' in rc_extras: username = rc_extras['username'] repository = rc_extras['repository'] scm = rc_extras['scm'] + make_lock = rc_extras['make_lock'] else: raise Exception('Missing data in repo.ui and os.environ') - + user = User.get_by_username(username) action = 'pull' - action_logger(username, action, repository, extras['ip'], commit=True) + action_logger(user, action, repository, extras['ip'], commit=True) # extension hook call from rhodecode import EXTENSIONS callback = getattr(EXTENSIONS, 'PULL_HOOK', None) @@ -117,6 +175,12 @@ def log_pull_action(ui, repo, **kwargs): kw = {} kw.update(extras) callback(**kw) + + if make_lock is True: + Repository.lock(Repository.get_by_repo_name(repository), user.user_id) + #msg = 'Made lock on repo `%s`' % repository + #sys.stdout.write(msg) + return 0 @@ -138,10 +202,12 @@ def log_push_action(ui, repo, **kwargs): username = extras['username'] repository = extras['repository'] scm = extras['scm'] + make_lock = extras['make_lock'] elif 'username' in rc_extras: username = rc_extras['username'] repository = rc_extras['repository'] scm = rc_extras['scm'] + make_lock = rc_extras['make_lock'] else: raise Exception('Missing data in repo.ui and os.environ') @@ -179,6 +245,12 @@ def log_push_action(ui, repo, **kwargs): kw = {'pushed_revs': revs} kw.update(extras) callback(**kw) + + if make_lock is False: + Repository.unlock(Repository.get_by_repo_name(repository)) + msg = 'Released lock on repo `%s`\n' % repository + sys.stdout.write(msg) + return 0 @@ -219,8 +291,13 @@ def log_create_repository(repository_dic return 0 +handle_git_pre_receive = (lambda repo_path, revs, env: + handle_git_receive(repo_path, revs, env, hook_type='pre')) +handle_git_post_receive = (lambda repo_path, revs, env: + handle_git_receive(repo_path, revs, env, hook_type='post')) -def handle_git_post_receive(repo_path, revs, env): + +def handle_git_receive(repo_path, revs, env, hook_type='post'): """ A really hacky method that is runned by git post-receive hook and logs an push action together with pushed revisions. It's executed by subprocess @@ -240,7 +317,6 @@ def handle_git_post_receive(repo_path, r from rhodecode.model import init_model from rhodecode.model.db import RhodeCodeUi from rhodecode.lib.utils import make_ui - from rhodecode.model.db import Repository path, ini_name = os.path.split(env['RHODECODE_CONFIG_FILE']) conf = appconfig('config:%s' % ini_name, relative_to=path) @@ -255,20 +331,18 @@ def handle_git_post_receive(repo_path, r repo_path = repo_path[:-4] repo = Repository.get_by_full_path(repo_path) _hooks = dict(baseui.configitems('hooks')) or {} - # if push hook is enabled via web interface - if repo and _hooks.get(RhodeCodeUi.HOOK_PUSH): - extras = { - 'username': env['RHODECODE_USER'], - 'repository': repo.repo_name, - 'scm': 'git', - 'action': 'push', - 'ip': env['RHODECODE_CONFIG_IP'], - } - for k, v in extras.items(): - baseui.setconfig('rhodecode_extras', k, v) - repo = repo.scm_instance - repo.ui = baseui + extras = json.loads(env['RHODECODE_EXTRAS']) + for k, v in extras.items(): + baseui.setconfig('rhodecode_extras', k, v) + repo = repo.scm_instance + repo.ui = baseui + + if hook_type == 'pre': + pre_push(baseui, repo) + + # if push hook is enabled via web interface + elif hook_type == 'post' and _hooks.get(RhodeCodeUi.HOOK_PUSH): rev_data = [] for l in revs: