Пример #1
0
def _hook_environment(repo_path):
    """
    Create a light-weight environment for stand-alone scripts and return an UI and the
    db repository.

    Git hooks are executed as subprocess of Git while Kallithea is waiting, and
    they thus need enough info to be able to create an app environment and
    connect to the database.
    """
    import paste.deploy
    import kallithea.config.middleware

    extras = get_hook_environment()

    path_to_ini_file = extras['config']
    kallithea.CONFIG = paste.deploy.appconfig('config:' + path_to_ini_file)
    #logging.config.fileConfig(ini_file_path) # Note: we are in a different process - don't use configured logging
    kallithea.config.middleware.make_app(kallithea.CONFIG.global_conf,
                                         **kallithea.CONFIG.local_conf)

    # fix if it's not a bare repo
    if repo_path.endswith(os.sep + '.git'):
        repo_path = repo_path[:-5]

    repo = Repository.get_by_full_path(repo_path)
    if not repo:
        raise OSError('Repository %s not found in database' % repo_path)

    baseui = make_ui()
    return baseui, repo
Пример #2
0
def handle_git_receive(repo_path, revs, env, hook_type):
    """
    A really hacky method that is run by git post-receive hook and logs
    a push action together with pushed revisions. It's executed by subprocess
    thus needs all info to be able to create an on the fly app environment,
    connect to database and run the logging code. Hacky as sh*t but works.

    :param repo_path:
    :param revs:
    :param env:
    """
    from paste.deploy import appconfig
    from sqlalchemy import engine_from_config
    from kallithea.config.environment import load_environment
    from kallithea.model.base import init_model
    from kallithea.model.db import Ui
    from kallithea.lib.utils import make_ui, setup_cache_regions
    extras = _extract_extras(env)

    repo_path = safe_unicode(repo_path)
    path, ini_name = os.path.split(extras['config'])
    conf = appconfig('config:%s' % ini_name, relative_to=path)
    conf = load_environment(conf.global_conf, conf.local_conf)

    setup_cache_regions(conf)

    engine = engine_from_config(conf, 'sqlalchemy.')
    init_model(engine)

    baseui = make_ui('db')
    # fix if it's not a bare repo
    if repo_path.endswith(os.sep + '.git'):
        repo_path = repo_path[:-5]

    repo = Repository.get_by_full_path(repo_path)
    if not repo:
        raise OSError('Repository %s not found in database' %
                      (safe_str(repo_path)))

    _hooks = dict(baseui.configitems('hooks')) or {}

    if hook_type == 'pre':
        repo = repo.scm_instance
    else:
        # post push shouldn't use the cached instance never
        repo = repo.scm_instance_no_cache()

    if hook_type == 'pre':
        pre_push(baseui, repo)

    # if push hook is enabled via web interface
    elif hook_type == 'post' and _hooks.get(Ui.HOOK_PUSH):
        rev_data = []
        for l in revs:
            old_rev, new_rev, ref = l.strip().split(' ')
            _ref_data = ref.split('/')
            if _ref_data[1] in ['tags', 'heads']:
                rev_data.append({
                    'old_rev': old_rev,
                    'new_rev': new_rev,
                    'ref': ref,
                    'type': _ref_data[1],
                    'name': '/'.join(_ref_data[2:])
                })

        git_revs = []

        for push_ref in rev_data:
            _type = push_ref['type']
            if _type == 'heads':
                if push_ref['old_rev'] == EmptyChangeset().raw_id:
                    # update the symbolic ref if we push new repo
                    if repo.is_empty():
                        repo._repo.refs.set_symbolic_ref(
                            'HEAD', 'refs/heads/%s' % push_ref['name'])

                    cmd = [
                        'for-each-ref', '--format=%(refname)', 'refs/heads/*'
                    ]
                    heads = repo.run_git_command(cmd)[0]
                    cmd = [
                        'log', push_ref['new_rev'], '--reverse',
                        '--pretty=format:%H', '--not'
                    ]
                    heads = heads.replace(push_ref['ref'], '')
                    for l in heads.splitlines():
                        cmd.append(l.strip())
                    git_revs += repo.run_git_command(cmd)[0].splitlines()

                elif push_ref['new_rev'] == EmptyChangeset().raw_id:
                    #delete branch case
                    git_revs += ['delete_branch=>%s' % push_ref['name']]
                else:
                    cmd = [
                        'log',
                        '%(old_rev)s..%(new_rev)s' % push_ref, '--reverse',
                        '--pretty=format:%H'
                    ]
                    git_revs += repo.run_git_command(cmd)[0].splitlines()

            elif _type == 'tags':
                git_revs += ['tag=>%s' % push_ref['name']]

        log_push_action(baseui, repo, _git_revs=git_revs)
Пример #3
0
def handle_git_receive(repo_path, revs, env, hook_type='post'):
    """
    A really hacky method that is run by git post-receive hook and logs
    an push action together with pushed revisions. It's executed by subprocess
    thus needs all info to be able to create a on the fly pylons environment,
    connect to database and run the logging code. Hacky as sh*t but works.

    :param repo_path:
    :param revs:
    :param env:
    """
    from paste.deploy import appconfig
    from sqlalchemy import engine_from_config
    from kallithea.config.environment import load_environment
    from kallithea.model import init_model
    from kallithea.model.db import Ui
    from kallithea.lib.utils import make_ui
    extras = _extract_extras(env)

    path, ini_name = os.path.split(extras['config'])
    conf = appconfig('config:%s' % ini_name, relative_to=path)
    load_environment(conf.global_conf, conf.local_conf, test_env=False,
                     test_index=False)

    engine = engine_from_config(conf, 'sqlalchemy.db1.')
    init_model(engine)

    baseui = make_ui('db')
    # fix if it's not a bare repo
    if repo_path.endswith(os.sep + '.git'):
        repo_path = repo_path[:-5]

    repo = Repository.get_by_full_path(repo_path)
    if not repo:
        raise OSError('Repository %s not found in database'
                      % (safe_str(repo_path)))

    _hooks = dict(baseui.configitems('hooks')) or {}

    if hook_type == 'pre':
        repo = repo.scm_instance
    else:
        #post push shouldn't use the cached instance never
        repo = repo.scm_instance_no_cache()

    if hook_type == 'pre':
        pre_push(baseui, repo)

    # if push hook is enabled via web interface
    elif hook_type == 'post' and _hooks.get(Ui.HOOK_PUSH):
        rev_data = []
        for l in revs:
            old_rev, new_rev, ref = l.split(' ')
            _ref_data = ref.split('/')
            if _ref_data[1] in ['tags', 'heads']:
                rev_data.append({'old_rev': old_rev,
                                 'new_rev': new_rev,
                                 'ref': ref,
                                 'type': _ref_data[1],
                                 'name': _ref_data[2].strip()})

        git_revs = []

        for push_ref in rev_data:
            _type = push_ref['type']
            if _type == 'heads':
                if push_ref['old_rev'] == EmptyChangeset().raw_id:
                    # update the symbolic ref if we push new repo
                    if repo.is_empty():
                        repo._repo.refs.set_symbolic_ref('HEAD',
                                            'refs/heads/%s' % push_ref['name'])

                    cmd = "for-each-ref --format='%(refname)' 'refs/heads/*'"
                    heads = repo.run_git_command(cmd)[0]
                    heads = heads.replace(push_ref['ref'], '')
                    heads = ' '.join(map(lambda c: c.strip('\n').strip(),
                                         heads.splitlines()))
                    cmd = (('log %(new_rev)s' % push_ref) +
                           ' --reverse --pretty=format:"%H" --not ' + heads)
                    git_revs += repo.run_git_command(cmd)[0].splitlines()

                elif push_ref['new_rev'] == EmptyChangeset().raw_id:
                    #delete branch case
                    git_revs += ['delete_branch=>%s' % push_ref['name']]
                else:
                    cmd = (('log %(old_rev)s..%(new_rev)s' % push_ref) +
                           ' --reverse --pretty=format:"%H"')
                    git_revs += repo.run_git_command(cmd)[0].splitlines()

            elif _type == 'tags':
                git_revs += ['tag=>%s' % push_ref['name']]

        log_push_action(baseui, repo, _git_revs=git_revs)