Blame progit/ui/repo.py

Pierre-Yves Chibon 47950c
#-*- coding: utf-8 -*-
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
"""
Pierre-Yves Chibon 8a5345
 (c) 2014-2015 - Copyright Red Hat Inc
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
 Authors:
Pierre-Yves Chibon 47950c
   Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
"""
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
import flask
Pierre-Yves Chibon 0c7b30
import shutil
Pierre-Yves Chibon 47950c
import os
Pierre-Yves Chibon 47950c
from math import ceil
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
import pygit2
Pierre-Yves Chibon e3aa95
from cStringIO import StringIO
Pierre-Yves Chibon 47950c
from sqlalchemy.exc import SQLAlchemyError
Pierre-Yves Chibon a1aa0b
from PIL import Image
Pierre-Yves Chibon 47950c
from pygments import highlight
Pierre-Yves Chibon 47950c
from pygments.formatters import HtmlFormatter
Johan Cwiklinski 5cd5a0
from pygments.lexers import guess_lexer_for_filename
Johan Cwiklinski 5cd5a0
from pygments.lexers.text import DiffLexer
Johan Cwiklinski 5cd5a0
from pygments.lexers.special import TextLexer
Johan Cwiklinski 5cd5a0
from pygments.util import ClassNotFound
Pierre-Yves Chibon 47950c
Johan Cwiklinski 740adc
import mimetypes
Johan Cwiklinski 740adc
import chardet
Johan Cwiklinski 740adc
Pierre-Yves Chibon 47950c
import progit.exceptions
Pierre-Yves Chibon 47950c
import progit.lib
Pierre-Yves Chibon 118968
import progit.lib.git
Pierre-Yves Chibon 47950c
import progit.forms
Pierre-Yves Chibon 05d0d7
import progit.ui.plugins
Pierre-Yves Chibon 0261ce
from progit import (APP, SESSION, LOG, __get_file_in_tree, cla_required,
Pierre-Yves Chibon 0261ce
                    is_repo_admin)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 2c6a7c
@APP.route('/<repo>')</repo>
Pierre-Yves Chibon 2c6a7c
@APP.route('/fork/<username>/<repo>')</repo></username>
Pierre-Yves Chibon 2c6a7c
def view_repo(repo, username=None):
Pierre-Yves Chibon 47950c
    """ Front page of a specific repo.
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if repo is None:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    reponame = os.path.join(APP.config['GIT_FOLDER'], repo.path)
Pierre-Yves Chibon 47950c
    if repo.is_fork:
Pierre-Yves Chibon 47950c
        reponame = os.path.join(APP.config['FORK_FOLDER'], repo.path)
Pierre-Yves Chibon 47950c
    repo_obj = pygit2.Repository(reponame)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    cnt = 0
Pierre-Yves Chibon 47950c
    last_commits = []
Pierre-Yves Chibon 47950c
    tree = []
Pierre-Yves Chibon 47950c
    if not repo_obj.is_empty:
Pierre-Yves Chibon 47950c
        for commit in repo_obj.walk(
Pierre-Yves Chibon 47950c
                repo_obj.head.target, pygit2.GIT_SORT_TIME):
Pierre-Yves Chibon 47950c
            last_commits.append(commit)
Pierre-Yves Chibon 47950c
            cnt += 1
Pierre-Yves Chibon 47950c
            if cnt == 10:
Pierre-Yves Chibon 47950c
                break
Pierre-Yves Chibon 47950c
        tree = sorted(last_commits[0].tree, key=lambda x: x.filemode)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    readme = None
Pierre-Yves Chibon 47950c
    for i in tree:
Pierre-Yves Chibon 47950c
        name, ext = os.path.splitext(i.name)
Pierre-Yves Chibon 47950c
        if name == 'README':
Pierre-Yves Chibon 47950c
            content = repo_obj[i.oid].data
Pierre-Yves Chibon 47950c
            readme = progit.doc_utils.convert_readme(content, ext)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    diff_commits = []
Pierre-Yves Chibon 47950c
    if repo.is_fork:
Pierre-Yves Chibon 47950c
        parentname = os.path.join(
Pierre-Yves Chibon 47950c
            APP.config['GIT_FOLDER'], repo.parent.path)
Pierre-Yves Chibon 26dbc9
        if repo.parent.is_fork:
Pierre-Yves Chibon 26dbc9
            parentname = os.path.join(
Pierre-Yves Chibon 26dbc9
                APP.config['FORK_FOLDER'], repo.parent.path)
Pierre-Yves Chibon 2c9e9f
    elif repo.parent:
Pierre-Yves Chibon 2c9e9f
        parentname = os.path.join(
Pierre-Yves Chibon 2c9e9f
            APP.config['GIT_FOLDER'], repo.parent.path)
Pierre-Yves Chibon 2c9e9f
    else:
Pierre-Yves Chibon 2c9e9f
        parentname = os.path.join(APP.config['GIT_FOLDER'], repo.path)
Pierre-Yves Chibon 2c9e9f
Pierre-Yves Chibon 2c9e9f
    orig_repo = pygit2.Repository(parentname)
Pierre-Yves Chibon 2c9e9f
Pierre-Yves Chibon 2c9e9f
    if not repo_obj.is_empty and not orig_repo.is_empty:
Pierre-Yves Chibon 2c9e9f
        orig_commit = orig_repo[
Pierre-Yves Chibon 2c9e9f
            orig_repo.lookup_branch('master').get_object().hex]
Pierre-Yves Chibon 2c9e9f
Pierre-Yves Chibon 2c9e9f
        master_commits = [
Pierre-Yves Chibon 2c9e9f
            commit.oid.hex
Pierre-Yves Chibon 2c9e9f
            for commit in orig_repo.walk(
Pierre-Yves Chibon 2c9e9f
                orig_repo.lookup_branch('master').get_object().hex,
Pierre-Yves Chibon 2c9e9f
                pygit2.GIT_SORT_TIME)
Pierre-Yves Chibon 2c9e9f
        ]
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 2c9e9f
        repo_commit = repo_obj[
Pierre-Yves Chibon 2c9e9f
            repo_obj.lookup_branch('master').get_object().hex]
Pierre-Yves Chibon acb942
Pierre-Yves Chibon 2c9e9f
        for commit in repo_obj.walk(
Pierre-Yves Chibon 2c9e9f
                repo_commit.oid.hex, pygit2.GIT_SORT_TIME):
Pierre-Yves Chibon 2c9e9f
            if commit.oid.hex in master_commits:
Pierre-Yves Chibon 2c9e9f
                break
Pierre-Yves Chibon 2c9e9f
            diff_commits.append(commit.oid.hex)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 47950c
        'repo_info.html',
Pierre-Yves Chibon 47950c
        select='overview',
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 47950c
        repo_obj=repo_obj,
Pierre-Yves Chibon 47950c
        username=username,
Pierre-Yves Chibon 47950c
        readme=readme,
Pierre-Yves Chibon 47950c
        branches=sorted(repo_obj.listall_branches()),
Pierre-Yves Chibon 47950c
        branchname='master',
Pierre-Yves Chibon 47950c
        last_commits=last_commits,
Pierre-Yves Chibon 47950c
        tree=tree,
Pierre-Yves Chibon 47950c
        diff_commits=diff_commits,
Pierre-Yves Chibon 47950c
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 2c6a7c
@APP.route('/<repo>/branch/<branchname>')</branchname></repo>
Pierre-Yves Chibon 2c6a7c
@APP.route('/fork/<username>/<repo>/branch/<branchname>')</branchname></repo></username>
Pierre-Yves Chibon 2c6a7c
def view_repo_branch(repo, branchname, username=None):
Pierre-Yves Chibon 47950c
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if not repo:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    reponame = os.path.join(APP.config['GIT_FOLDER'], repo.path)
Pierre-Yves Chibon 47950c
    if repo.is_fork:
Pierre-Yves Chibon 47950c
        reponame = os.path.join(APP.config['FORK_FOLDER'], repo.path)
Pierre-Yves Chibon 47950c
    repo_obj = pygit2.Repository(reponame)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 05748c
    if branchname not in repo_obj.listall_branches():
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Branch no found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    branch = repo_obj.lookup_branch(branchname)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    cnt = 0
Pierre-Yves Chibon 47950c
    last_commits = []
Pierre-Yves Chibon 47950c
    for commit in repo_obj.walk(branch.get_object().hex, pygit2.GIT_SORT_TIME):
Pierre-Yves Chibon 47950c
        last_commits.append(commit)
Pierre-Yves Chibon 47950c
        cnt += 1
Pierre-Yves Chibon 47950c
        if cnt == 10:
Pierre-Yves Chibon 47950c
            break
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    diff_commits = []
Pierre-Yves Chibon 47950c
    if repo.is_fork:
Pierre-Yves Chibon 47950c
        parentname = os.path.join(
Pierre-Yves Chibon 47950c
            APP.config['GIT_FOLDER'], repo.parent.path)
Pierre-Yves Chibon 26dbc9
        if repo.parent.is_fork:
Pierre-Yves Chibon 26dbc9
            parentname = os.path.join(
Pierre-Yves Chibon 26dbc9
                APP.config['FORK_FOLDER'], repo.parent.path)
Pierre-Yves Chibon 2c9e9f
    elif repo.parent:
Pierre-Yves Chibon 2c9e9f
        parentname = os.path.join(
Pierre-Yves Chibon 2c9e9f
            APP.config['GIT_FOLDER'], repo.parent.path)
Pierre-Yves Chibon 2c9e9f
    else:
Pierre-Yves Chibon 2c9e9f
        parentname = os.path.join(APP.config['GIT_FOLDER'], repo.path)
Pierre-Yves Chibon 2c9e9f
Pierre-Yves Chibon 2c9e9f
    orig_repo = pygit2.Repository(parentname)
Pierre-Yves Chibon 26dbc9
Pierre-Yves Chibon 2c9e9f
    if not repo_obj.is_empty and not orig_repo.is_empty:
Pierre-Yves Chibon 2c9e9f
        orig_commit = orig_repo[
Pierre-Yves Chibon 2c9e9f
            orig_repo.lookup_branch('master').get_object().hex]
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 2c9e9f
        master_commits = [
Pierre-Yves Chibon 2c9e9f
            commit.oid.hex
Pierre-Yves Chibon 2c9e9f
            for commit in orig_repo.walk(
Pierre-Yves Chibon 2c9e9f
                orig_repo.lookup_branch('master').get_object().hex,
Pierre-Yves Chibon 2c9e9f
                pygit2.GIT_SORT_TIME)
Pierre-Yves Chibon 2c9e9f
        ]
Pierre-Yves Chibon acb942
Pierre-Yves Chibon 2c9e9f
        repo_commit = repo_obj[branch.get_object().hex]
Pierre-Yves Chibon 2c9e9f
Pierre-Yves Chibon 2c9e9f
        for commit in repo_obj.walk(
Pierre-Yves Chibon 2c9e9f
                repo_commit.oid.hex, pygit2.GIT_SORT_TIME):
Pierre-Yves Chibon 2c9e9f
            if commit.oid.hex in master_commits:
Pierre-Yves Chibon 2c9e9f
                break
Pierre-Yves Chibon 2c9e9f
            diff_commits.append(commit.oid.hex)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 47950c
        'repo_info.html',
Pierre-Yves Chibon 47950c
        select='overview',
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 47950c
        username=username,
Pierre-Yves Chibon 47950c
        branches=sorted(repo_obj.listall_branches()),
Pierre-Yves Chibon 47950c
        branchname=branchname,
Pierre-Yves Chibon 47950c
        last_commits=last_commits,
Pierre-Yves Chibon 47950c
        tree=sorted(last_commits[0].tree, key=lambda x: x.filemode),
Pierre-Yves Chibon 47950c
        diff_commits=diff_commits,
Pierre-Yves Chibon 47950c
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 2c6a7c
@APP.route('/<repo>/log')</repo>
Pierre-Yves Chibon 2c6a7c
@APP.route('/<repo>/log/<branchname>')</branchname></repo>
Pierre-Yves Chibon 2c6a7c
@APP.route('/fork/<username>/<repo>/log')</repo></username>
Pierre-Yves Chibon 2c6a7c
@APP.route('/fork/<username>/<repo>/log/<branchname>')</branchname></repo></username>
Pierre-Yves Chibon 2c6a7c
def view_log(repo, branchname=None, username=None):
Pierre-Yves Chibon 47950c
    """ Displays the logs of the specified repo.
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if not repo:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    reponame = os.path.join(APP.config['GIT_FOLDER'], repo.path)
Pierre-Yves Chibon 47950c
    if repo.is_fork:
Pierre-Yves Chibon 47950c
        reponame = os.path.join(APP.config['FORK_FOLDER'], repo.path)
Pierre-Yves Chibon 47950c
    repo_obj = pygit2.Repository(reponame)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 05748c
    if branchname and branchname not in repo_obj.listall_branches():
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Branch no found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if branchname:
Pierre-Yves Chibon 47950c
        branch = repo_obj.lookup_branch(branchname)
Pierre-Yves Chibon 47950c
    else:
Pierre-Yves Chibon 47950c
        branch = repo_obj.lookup_branch('master')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    try:
Pierre-Yves Chibon 47950c
        page = int(flask.request.args.get('page', 1))
Pierre-Yves Chibon 47950c
    except ValueError:
Pierre-Yves Chibon 47950c
        page = 1
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    limit = APP.config['ITEM_PER_PAGE']
Pierre-Yves Chibon 47950c
    start = limit * (page - 1)
Pierre-Yves Chibon 47950c
    end = limit * page
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    n_commits = 0
Pierre-Yves Chibon 47950c
    last_commits = []
Pierre-Yves Chibon c184e7
    if branch:
Pierre-Yves Chibon c184e7
        for commit in repo_obj.walk(
Pierre-Yves Chibon c184e7
                branch.get_object().hex, pygit2.GIT_SORT_TIME):
Pierre-Yves Chibon c184e7
            if n_commits >= start and n_commits <= end:
Pierre-Yves Chibon c184e7
                last_commits.append(commit)
Pierre-Yves Chibon c184e7
            n_commits += 1
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    total_page = int(ceil(n_commits / float(limit)))
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    diff_commits = []
Pierre-Yves Chibon 47950c
    if repo.is_fork:
Pierre-Yves Chibon 47950c
        parentname = os.path.join(
Pierre-Yves Chibon 47950c
            APP.config['GIT_FOLDER'], repo.parent.path)
Pierre-Yves Chibon 26dbc9
        if repo.parent.is_fork:
Pierre-Yves Chibon 26dbc9
            parentname = os.path.join(
Pierre-Yves Chibon 26dbc9
                APP.config['FORK_FOLDER'], repo.parent.path)
Pierre-Yves Chibon 2c9e9f
    elif repo.parent:
Pierre-Yves Chibon 2c9e9f
        parentname = os.path.join(
Pierre-Yves Chibon 2c9e9f
            APP.config['GIT_FOLDER'], repo.parent.path)
Pierre-Yves Chibon 2c9e9f
    else:
Pierre-Yves Chibon 2c9e9f
        parentname = os.path.join(APP.config['GIT_FOLDER'], repo.path)
Pierre-Yves Chibon 26dbc9
Pierre-Yves Chibon 2c9e9f
    orig_repo = pygit2.Repository(parentname)
Pierre-Yves Chibon acb942
Pierre-Yves Chibon 2c9e9f
    if not repo_obj.is_empty and not orig_repo.is_empty:
Pierre-Yves Chibon 2c9e9f
        orig_commit = orig_repo[
Pierre-Yves Chibon 2c9e9f
            orig_repo.lookup_branch('master').get_object().hex]
Pierre-Yves Chibon 2c9e9f
Pierre-Yves Chibon 2c9e9f
        master_commits = [
Pierre-Yves Chibon 2c9e9f
            commit.oid.hex
Pierre-Yves Chibon 2c9e9f
            for commit in orig_repo.walk(
Pierre-Yves Chibon 2c9e9f
                orig_repo.lookup_branch('master').get_object().hex,
Pierre-Yves Chibon 2c9e9f
                pygit2.GIT_SORT_TIME)
Pierre-Yves Chibon 2c9e9f
        ]
Pierre-Yves Chibon 2c9e9f
Pierre-Yves Chibon 2c9e9f
        repo_commit = repo_obj[branch.get_object().hex]
Pierre-Yves Chibon 2c9e9f
Pierre-Yves Chibon 2c9e9f
        for commit in repo_obj.walk(
Pierre-Yves Chibon 2c9e9f
                repo_commit.oid.hex, pygit2.GIT_SORT_TIME):
Pierre-Yves Chibon 2c9e9f
            if commit.oid.hex in master_commits:
Pierre-Yves Chibon 2c9e9f
                break
Pierre-Yves Chibon 2c9e9f
            diff_commits.append(commit.oid.hex)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    origin = 'view_log'
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 47950c
        'repo_info.html',
Pierre-Yves Chibon 47950c
        select='logs',
Pierre-Yves Chibon 47950c
        origin=origin,
Pierre-Yves Chibon c184e7
        repo_obj=repo_obj,
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 47950c
        username=username,
Pierre-Yves Chibon 47950c
        branches=sorted(repo_obj.listall_branches()),
Pierre-Yves Chibon 47950c
        branchname=branchname,
Pierre-Yves Chibon 47950c
        last_commits=last_commits,
Pierre-Yves Chibon 47950c
        diff_commits=diff_commits,
Pierre-Yves Chibon 47950c
        page=page,
Pierre-Yves Chibon 47950c
        total_page=total_page,
Pierre-Yves Chibon 47950c
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 2c6a7c
@APP.route('/<repo>/blob/<identifier>/<path:filename>')</path:filename></identifier></repo>
Pierre-Yves Chibon 2c6a7c
@APP.route('/fork/<username>/<repo>/blob/<identifier>/<path:filename>')</path:filename></identifier></repo></username>
Pierre-Yves Chibon 2c6a7c
def view_file(repo, identifier, filename, username=None):
Pierre-Yves Chibon 47950c
    """ Displays the content of a file or a tree for the specified repo.
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if not repo:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    reponame = os.path.join(APP.config['GIT_FOLDER'], repo.path)
Pierre-Yves Chibon 47950c
    if repo.is_fork:
Pierre-Yves Chibon 47950c
        reponame = os.path.join(APP.config['FORK_FOLDER'], repo.path)
Pierre-Yves Chibon 47950c
    repo_obj = pygit2.Repository(reponame)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if identifier in repo_obj.listall_branches():
Pierre-Yves Chibon 47950c
        branchname = identifier
Pierre-Yves Chibon 47950c
        branch = repo_obj.lookup_branch(identifier)
Pierre-Yves Chibon 47950c
        commit = branch.get_object()
Pierre-Yves Chibon 47950c
    else:
Pierre-Yves Chibon 47950c
        try:
Pierre-Yves Chibon 47950c
            commit = repo_obj.get(identifier)
Pierre-Yves Chibon 47950c
            branchname = identifier
Pierre-Yves Chibon 47950c
        except ValueError:
Pierre-Yves Chibon 47950c
            # If it's not a commit id then it's part of the filename
Pierre-Yves Chibon 47950c
            commit = repo_obj[repo_obj.head.target]
Pierre-Yves Chibon 47950c
            branchname = 'master'
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon f74707
    if commit and not isinstance(commit, pygit2.Blob):
Pierre-Yves Chibon f74707
        content = __get_file_in_tree(
Pierre-Yves Chibon f74707
            repo_obj, commit.tree, filename.split('/'))
Pierre-Yves Chibon f74707
        if not content:
Pierre-Yves Chibon f74707
            flask.abort(404, 'File not found')
Pierre-Yves Chibon f74707
        content = repo_obj[content.oid]
Pierre-Yves Chibon f74707
    else:
Pierre-Yves Chibon f74707
        content = commit
Pierre-Yves Chibon f74707
Pierre-Yves Chibon 47950c
    if not content:
Pierre-Yves Chibon f74707
            flask.abort(404, 'File not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if isinstance(content, pygit2.Blob):
Johan Cwiklinski 740adc
        if content.is_binary:
Johan Cwiklinski 740adc
            ext = filename[filename.rfind('.'):]
Johan Cwiklinski 740adc
            if ext in ('.gif', '.png', '.bmp', '.tif', '.tiff', '.jpg',
Johan Cwiklinski 740adc
                    '.jpeg', '.ppm', '.pnm', '.pbm', '.pgm', '.webp', '.ico'):
Pierre-Yves Chibon a1aa0b
                try:
Pierre-Yves Chibon e3aa95
                    Image.open(StringIO(content.data))
Pierre-Yves Chibon a1aa0b
                    output_type = 'image'
Pierre-Yves Chibon 1f3f7b
                except IOError as err:
Pierre-Yves Chibon 6716f6
                    LOG.debug(
Pierre-Yves Chibon 1f3f7b
                        'Failed to load image %s, error: %s', filename, err
Pierre-Yves Chibon 1f3f7b
                    )
Pierre-Yves Chibon a1aa0b
                    output_type = 'binary'
Johan Cwiklinski 740adc
            else:
Johan Cwiklinski 740adc
                output_type = 'binary'
Johan Cwiklinski 740adc
        else:
Johan Cwiklinski 5cd5a0
            try:
Johan Cwiklinski 5cd5a0
                lexer = guess_lexer_for_filename(
Johan Cwiklinski 5cd5a0
                    filename,
Johan Cwiklinski 5cd5a0
                    content.data
Johan Cwiklinski 5cd5a0
                )
Johan Cwiklinski 5cd5a0
            except ClassNotFound:
Johan Cwiklinski 5cd5a0
                lexer = TextLexer()
Johan Cwiklinski 5cd5a0
Johan Cwiklinski 740adc
            content = highlight(
Johan Cwiklinski 740adc
                content.data,
Johan Cwiklinski 5cd5a0
                lexer,
Johan Cwiklinski 740adc
                HtmlFormatter(
Johan Cwiklinski 740adc
                    noclasses=True,
Johan Cwiklinski 740adc
                    style="tango",)
Johan Cwiklinski 740adc
            )
Johan Cwiklinski 740adc
            output_type = 'file'
Pierre-Yves Chibon 47950c
    else:
Pierre-Yves Chibon 47950c
        content = sorted(content, key=lambda x: x.filemode)
Pierre-Yves Chibon 47950c
        output_type = 'tree'
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 47950c
        'file.html',
Pierre-Yves Chibon 47950c
        select='tree',
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 47950c
        username=username,
Pierre-Yves Chibon 47950c
        branchname=branchname,
Pierre-Yves Chibon 47950c
        filename=filename,
Pierre-Yves Chibon 47950c
        content=content,
Pierre-Yves Chibon 47950c
        output_type=output_type,
Pierre-Yves Chibon 47950c
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Johan Cwiklinski 002118
@APP.route('/<repo>/raw/<identifier>', defaults={'filename': None})</identifier></repo>
Johan Cwiklinski 740adc
@APP.route('/<repo>/raw/<identifier>/<path:filename>')</path:filename></identifier></repo>
Johan Cwiklinski 002118
@APP.route('/fork/<username>/<repo>/raw/<identifier>', defaults={'filename': None})</identifier></repo></username>
Johan Cwiklinski 740adc
@APP.route('/fork/<username>/<repo>/raw/<identifier>/<path:filename>')</path:filename></identifier></repo></username>
Johan Cwiklinski 002118
def view_raw_file(repo, identifier, filename=None, username=None):
Johan Cwiklinski 002118
    """ Displays the raw content of a file of a commit for the specified repo.
Johan Cwiklinski 740adc
    """
Johan Cwiklinski 740adc
    repo = progit.lib.get_project(SESSION, repo, user=username)
Johan Cwiklinski 740adc
Johan Cwiklinski 740adc
    if not repo:
Johan Cwiklinski 740adc
        flask.abort(404, 'Project not found')
Johan Cwiklinski 740adc
Johan Cwiklinski 740adc
    reponame = os.path.join(APP.config['GIT_FOLDER'], repo.path)
Johan Cwiklinski 740adc
    if repo.is_fork:
Johan Cwiklinski 740adc
        reponame = os.path.join(APP.config['FORK_FOLDER'], repo.path)
Johan Cwiklinski 740adc
    repo_obj = pygit2.Repository(reponame)
Johan Cwiklinski 740adc
Johan Cwiklinski 740adc
    if identifier in repo_obj.listall_branches():
Johan Cwiklinski 740adc
        branch = repo_obj.lookup_branch(identifier)
Johan Cwiklinski 740adc
        commit = branch.get_object()
Johan Cwiklinski 740adc
    else:
Johan Cwiklinski 740adc
        try:
Johan Cwiklinski 740adc
            commit = repo_obj.get(identifier)
Johan Cwiklinski 740adc
        except ValueError:
Johan Cwiklinski 740adc
            # If it's not a commit id then it's part of the filename
Johan Cwiklinski 740adc
            commit = repo_obj[repo_obj.head.target]
Johan Cwiklinski 740adc
Johan Cwiklinski 002118
    mimetype = None
Johan Cwiklinski 002118
    encoding = None
Johan Cwiklinski 002118
    if filename:
Johan Cwiklinski 002118
        content = __get_file_in_tree(repo_obj, commit.tree, filename.split('/'))
Johan Cwiklinski 002118
        if not content:
Johan Cwiklinski 002118
            flask.abort(404, 'File not found')
Johan Cwiklinski 002118
Johan Cwiklinski 002118
        mimetype, encoding = mimetypes.guess_type(filename)
Johan Cwiklinski 002118
        data = repo_obj[content.oid].data
Johan Cwiklinski 002118
    else:
Johan Cwiklinski 002118
        if commit.parents:
Johan Cwiklinski 002118
            diff = commit.tree.diff_to_tree()
Johan Cwiklinski 740adc
Johan Cwiklinski 002118
            parent = repo_obj.revparse_single('%s^' % identifier)
Johan Cwiklinski 002118
            diff = repo_obj.diff(parent, commit)
Johan Cwiklinski 002118
        else:
Johan Cwiklinski 002118
            # First commit in the repo
Johan Cwiklinski 002118
            diff = commit.tree.diff_to_tree(swap=True)
Johan Cwiklinski 002118
        data = diff.patch
Johan Cwiklinski 740adc
Johan Cwiklinski 740adc
    if not mimetype and data[:2] == '#!':
Johan Cwiklinski 740adc
        mimetype = 'text/plain'
Johan Cwiklinski 740adc
Johan Cwiklinski 740adc
    if not mimetype:
Johan Cwiklinski 740adc
        if '\0' in data:
Johan Cwiklinski 740adc
            mimetype = 'application/octet-stream'
Johan Cwiklinski 740adc
        else:
Johan Cwiklinski 740adc
            mimetype = 'text/plain'
Johan Cwiklinski 740adc
Johan Cwiklinski 740adc
    if mimetype.startswith('text/') and not encoding:
Pierre-Yves Chibon e11904
        encoding = chardet.detect(bytes(data))['encoding']
Johan Cwiklinski 740adc
Johan Cwiklinski 740adc
    headers = {'Content-Type': mimetype}
Johan Cwiklinski 740adc
    if encoding:
Johan Cwiklinski 740adc
        headers['Content-Encoding'] = encoding
Johan Cwiklinski 740adc
Johan Cwiklinski 740adc
    return (data, 200, headers)
Johan Cwiklinski 740adc
Johan Cwiklinski 740adc
Pierre-Yves Chibon 2c6a7c
@APP.route('/<repo>/<commitid>')</commitid></repo>
Pierre-Yves Chibon 2c6a7c
@APP.route('/fork/<username>/<repo>/<commitid>')</commitid></repo></username>
Pierre-Yves Chibon 2c6a7c
def view_commit(repo, commitid, username=None):
Pierre-Yves Chibon 47950c
    """ Render a commit in a repo
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if not repo:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    reponame = os.path.join(APP.config['GIT_FOLDER'], repo.path)
Pierre-Yves Chibon 47950c
    if repo.is_fork:
Pierre-Yves Chibon 47950c
        reponame = os.path.join(APP.config['FORK_FOLDER'], repo.path)
Pierre-Yves Chibon 47950c
    repo_obj = pygit2.Repository(reponame)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    try:
Pierre-Yves Chibon 47950c
        commit = repo_obj.get(commitid)
Pierre-Yves Chibon 47950c
    except ValueError:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Commit not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 0a3e63
    if commit is None:
Pierre-Yves Chibon 0a3e63
        flask.abort(404, 'Commit not found')
Pierre-Yves Chibon 0a3e63
Pierre-Yves Chibon 47950c
    if commit.parents:
Pierre-Yves Chibon 47950c
        diff = commit.tree.diff_to_tree()
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
        parent = repo_obj.revparse_single('%s^' % commitid)
Pierre-Yves Chibon 47950c
        diff = repo_obj.diff(parent, commit)
Pierre-Yves Chibon 47950c
    else:
Pierre-Yves Chibon 47950c
        # First commit in the repo
Pierre-Yves Chibon 47950c
        diff = commit.tree.diff_to_tree(swap=True)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 47950c
        'commit.html',
Pierre-Yves Chibon 47950c
        select='logs',
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 47950c
        username=username,
Pierre-Yves Chibon 47950c
        commitid=commitid,
Pierre-Yves Chibon 47950c
        commit=commit,
Pierre-Yves Chibon 47950c
        diff=diff,
Pierre-Yves Chibon 47950c
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 74eefa
@APP.route('/<repo>/<commitid>.patch')</commitid></repo>
Pierre-Yves Chibon 74eefa
@APP.route('/fork/<username>/<repo>/<commitid>.patch')</commitid></repo></username>
Pierre-Yves Chibon 74eefa
def view_commit_patch(repo, commitid, username=None):
Pierre-Yves Chibon 74eefa
    """ Render a commit in a repo as patch
Pierre-Yves Chibon 74eefa
    """
Pierre-Yves Chibon 74eefa
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 74eefa
Pierre-Yves Chibon 74eefa
    if not repo:
Pierre-Yves Chibon 74eefa
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 74eefa
Pierre-Yves Chibon 74eefa
    reponame = os.path.join(APP.config['GIT_FOLDER'], repo.path)
Pierre-Yves Chibon 74eefa
    if repo.is_fork:
Pierre-Yves Chibon 74eefa
        reponame = os.path.join(APP.config['FORK_FOLDER'], repo.path)
Pierre-Yves Chibon 74eefa
    repo_obj = pygit2.Repository(reponame)
Pierre-Yves Chibon 74eefa
Pierre-Yves Chibon 74eefa
    try:
Pierre-Yves Chibon 74eefa
        commit = repo_obj.get(commitid)
Pierre-Yves Chibon 74eefa
    except ValueError:
Pierre-Yves Chibon 74eefa
        flask.abort(404, 'Commit not found')
Pierre-Yves Chibon 74eefa
Pierre-Yves Chibon 118968
    patch = progit.lib.git.commit_to_patch(repo_obj, commit)
Pierre-Yves Chibon 74eefa
Pierre-Yves Chibon 74eefa
    return flask.Response(patch, content_type="text/plain;charset=UTF-8")
Pierre-Yves Chibon 74eefa
Pierre-Yves Chibon 74eefa
Pierre-Yves Chibon 2c6a7c
@APP.route('/<repo>/tree/')</repo>
Pierre-Yves Chibon 2c6a7c
@APP.route('/<repo>/tree/<identifier>')</identifier></repo>
Pierre-Yves Chibon 2c6a7c
@APP.route('/fork/<username>/<repo>/tree/')</repo></username>
Pierre-Yves Chibon 2c6a7c
@APP.route('/fork/<username>/<repo>/tree/<identifier>')</identifier></repo></username>
Pierre-Yves Chibon 2c6a7c
def view_tree(repo, identifier=None, username=None):
Pierre-Yves Chibon 47950c
    """ Render the tree of the repo
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if repo is None:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    reponame = os.path.join(APP.config['GIT_FOLDER'], repo.path)
Pierre-Yves Chibon 47950c
    if repo.is_fork:
Pierre-Yves Chibon 47950c
        reponame = os.path.join(APP.config['FORK_FOLDER'], repo.path)
Pierre-Yves Chibon 47950c
    repo_obj = pygit2.Repository(reponame)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon c184e7
    branchname = None
Pierre-Yves Chibon c184e7
    content = None
Pierre-Yves Chibon c184e7
    output_type = None
Pierre-Yves Chibon c184e7
    if not repo_obj.is_empty:
Pierre-Yves Chibon c184e7
        if identifier in repo_obj.listall_branches():
Pierre-Yves Chibon 47950c
            branchname = identifier
Pierre-Yves Chibon c184e7
            branch = repo_obj.lookup_branch(identifier)
Pierre-Yves Chibon c184e7
            commit = branch.get_object()
Pierre-Yves Chibon c184e7
        else:
Pierre-Yves Chibon c184e7
            try:
Pierre-Yves Chibon c184e7
                commit = repo_obj.get(identifier)
Pierre-Yves Chibon c184e7
                branchname = identifier
Pierre-Yves Chibon c184e7
            except (ValueError, TypeError):
Pierre-Yves Chibon c184e7
                # If it's not a commit id then it's part of the filename
Pierre-Yves Chibon c184e7
                commit = repo_obj[repo_obj.head.target]
Pierre-Yves Chibon c184e7
                branchname = 'master'
Pierre-Yves Chibon c184e7
Pierre-Yves Chibon c184e7
        content = sorted(commit.tree, key=lambda x: x.filemode)
Pierre-Yves Chibon c184e7
        output_type = 'tree'
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 47950c
        'file.html',
Pierre-Yves Chibon 47950c
        select='tree',
Pierre-Yves Chibon c184e7
        repo_obj=repo_obj,
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 47950c
        username=username,
Pierre-Yves Chibon 47950c
        branchname=branchname,
Pierre-Yves Chibon 47950c
        filename='',
Pierre-Yves Chibon 47950c
        content=content,
Pierre-Yves Chibon 47950c
        output_type=output_type,
Pierre-Yves Chibon 47950c
    )
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 2c6a7c
@APP.route('/<repo>/forks')</repo>
Pierre-Yves Chibon 2c6a7c
@APP.route('/fork/<username>/<repo>/forks')</repo></username>
Pierre-Yves Chibon 2c6a7c
def view_forks(repo, username=None):
Pierre-Yves Chibon 2c6a7c
    """ Presents all the forks of the project.
Pierre-Yves Chibon 47950c
    """
Pierre-Yves Chibon 47950c
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    if not repo:
Pierre-Yves Chibon 47950c
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 47950c
Pierre-Yves Chibon 47950c
    return flask.render_template(
Pierre-Yves Chibon 47950c
        'forks.html',
Pierre-Yves Chibon 47950c
        select='forks',
Pierre-Yves Chibon ea8735
        username=username,
Pierre-Yves Chibon 47950c
        repo=repo,
Pierre-Yves Chibon 47950c
    )
Pierre-Yves Chibon 0261ce
Pierre-Yves Chibon 0261ce
Pierre-Yves Chibon 0261ce
@APP.route('/<repo>/settings', methods=('GET', 'POST'))</repo>
Pierre-Yves Chibon 0261ce
@APP.route('/fork/<username>/<repo>/settings', methods=('GET', 'POST'))</repo></username>
Pierre-Yves Chibon 0261ce
@cla_required
Pierre-Yves Chibon 0261ce
def view_settings(repo, username=None):
Pierre-Yves Chibon 0261ce
    """ Presents the settings of the project.
Pierre-Yves Chibon 0261ce
    """
Pierre-Yves Chibon 0261ce
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 0261ce
Pierre-Yves Chibon 0261ce
    if not repo:
Pierre-Yves Chibon 0261ce
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 0261ce
Pierre-Yves Chibon 0261ce
    if not is_repo_admin(repo):
Pierre-Yves Chibon 0261ce
        flask.abort(
Pierre-Yves Chibon 0261ce
            403,
Pierre-Yves Chibon 0261ce
            'You are not allowed to change the settings for this project')
Pierre-Yves Chibon 0261ce
Pierre-Yves Chibon 05d0d7
    plugins = progit.ui.plugins.get_plugin_names()
Pierre-Yves Chibon 77cd34
    tags = progit.lib.get_tags_of_project(SESSION, repo)
Pierre-Yves Chibon 58eba3
Pierre-Yves Chibon 0261ce
    form = progit.forms.ProjectSettingsForm()
Pierre-Yves Chibon 77cd34
    tag_form = progit.forms.AddIssueTagForm()
Pierre-Yves Chibon 0261ce
Pierre-Yves Chibon 0261ce
    if form.validate_on_submit():
Pierre-Yves Chibon 0261ce
        issue_tracker = form.issue_tracker.data
Pierre-Yves Chibon 0261ce
        project_docs = form.project_docs.data
Pierre-Yves Chibon 0261ce
Pierre-Yves Chibon 0261ce
        try:
Pierre-Yves Chibon 0261ce
            message = progit.lib.update_project_settings(
Pierre-Yves Chibon 0261ce
                SESSION,
Pierre-Yves Chibon 0261ce
                repo=repo,
Pierre-Yves Chibon 0261ce
                issue_tracker=issue_tracker,
Pierre-Yves Chibon 0261ce
                project_docs=project_docs,
Pierre-Yves Chibon 0261ce
            )
Pierre-Yves Chibon 0261ce
            SESSION.commit()
Pierre-Yves Chibon 0261ce
            flask.flash(message)
Pierre-Yves Chibon 0261ce
            return flask.redirect(flask.url_for(
Pierre-Yves Chibon de2ce2
                'view_repo', username=username, repo=repo.name))
Pierre-Yves Chibon 0261ce
        except progit.exceptions.ProgitException, err:
Pierre-Yves Chibon 0261ce
            flask.flash(str(err), 'error')
Pierre-Yves Chibon 0261ce
        except SQLAlchemyError, err:  # pragma: no cover
Pierre-Yves Chibon 0261ce
            SESSION.rollback()
Pierre-Yves Chibon 0261ce
            flask.flash(str(err), 'error')
Pierre-Yves Chibon 0261ce
    elif flask.request.method == 'GET':
Pierre-Yves Chibon 0261ce
        form = progit.forms.ProjectSettingsForm(project=repo)
Pierre-Yves Chibon 0261ce
Pierre-Yves Chibon 0261ce
    return flask.render_template(
Pierre-Yves Chibon 0261ce
        'settings.html',
Pierre-Yves Chibon 0261ce
        select='settings',
Pierre-Yves Chibon 0261ce
        username=username,
Pierre-Yves Chibon 0261ce
        repo=repo,
Pierre-Yves Chibon 0261ce
        form=form,
Pierre-Yves Chibon 77cd34
        tag_form=tag_form,
Pierre-Yves Chibon 77cd34
        tags=tags,
Pierre-Yves Chibon 58eba3
        plugins=plugins,
Pierre-Yves Chibon 0261ce
    )
Pierre-Yves Chibon 55a6e0
Pierre-Yves Chibon 55a6e0
Pierre-Yves Chibon 64a70d
@APP.route('/<repo>/updatedesc', methods=['POST'])</repo>
Pierre-Yves Chibon 64a70d
@APP.route('/fork/<username>/<repo>/updatedesc', methods=['POST'])</repo></username>
Pierre-Yves Chibon 64a70d
@cla_required
Pierre-Yves Chibon 64a70d
def update_description(repo, username=None):
Pierre-Yves Chibon 64a70d
    """ Update the description of a project.
Pierre-Yves Chibon 64a70d
    """
Pierre-Yves Chibon 64a70d
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 64a70d
Pierre-Yves Chibon 64a70d
    if not repo:
Pierre-Yves Chibon 64a70d
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 64a70d
Pierre-Yves Chibon 64a70d
    if not is_repo_admin(repo):
Pierre-Yves Chibon 64a70d
        flask.abort(
Pierre-Yves Chibon 64a70d
            403,
Pierre-Yves Chibon 64a70d
            'You are not allowed to change the settings for this project')
Pierre-Yves Chibon 64a70d
Pierre-Yves Chibon 64a70d
    form = progit.forms.DescriptionForm()
Pierre-Yves Chibon 64a70d
Pierre-Yves Chibon 64a70d
    if form.validate_on_submit():
Pierre-Yves Chibon 64a70d
        try:
Pierre-Yves Chibon 64a70d
            repo.description = form.description.data
Pierre-Yves Chibon 64a70d
            SESSION.add(repo)
Pierre-Yves Chibon 64a70d
            SESSION.commit()
Pierre-Yves Chibon 64a70d
            flask.flash('Description updated')
Pierre-Yves Chibon 64a70d
        except SQLAlchemyError, err:  # pragma: no cover
Pierre-Yves Chibon 64a70d
            SESSION.rollback()
Pierre-Yves Chibon 64a70d
            flask.flash(str(err), 'error')
Pierre-Yves Chibon 64a70d
Pierre-Yves Chibon 64a70d
    return flask.redirect(flask.url_for(
Pierre-Yves Chibon 64a70d
        'view_settings', username=username, repo=repo.name))
Pierre-Yves Chibon 64a70d
Pierre-Yves Chibon 64a70d
Pierre-Yves Chibon 55a6e0
@APP.route('/<repo>/delete', methods=['POST'])</repo>
Pierre-Yves Chibon 55a6e0
@APP.route('/fork/<username>/<repo>/delete', methods=['POST'])</repo></username>
Pierre-Yves Chibon 55a6e0
@cla_required
Pierre-Yves Chibon 55a6e0
def delete_repo(repo, username=None):
Pierre-Yves Chibon 55a6e0
    """ Delete the present project.
Pierre-Yves Chibon 55a6e0
    """
Pierre-Yves Chibon 55a6e0
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 55a6e0
Pierre-Yves Chibon 55a6e0
    if not repo:
Pierre-Yves Chibon 55a6e0
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 55a6e0
Pierre-Yves Chibon 55a6e0
    if not is_repo_admin(repo):
Pierre-Yves Chibon 55a6e0
        flask.abort(
Pierre-Yves Chibon 55a6e0
            403,
Pierre-Yves Chibon 55a6e0
            'You are not allowed to change the settings for this project')
Pierre-Yves Chibon 55a6e0
Pierre-Yves Chibon 55a6e0
    SESSION.delete(repo)
Pierre-Yves Chibon 55a6e0
Pierre-Yves Chibon 0c7b30
    repopath = os.path.join(APP.config['GIT_FOLDER'], repo.path)
Pierre-Yves Chibon 0c7b30
    if repo.is_fork:
Pierre-Yves Chibon 0c7b30
        repopath = os.path.join(APP.config['FORK_FOLDER'], repo.path)
Pierre-Yves Chibon 0c7b30
    docpath = os.path.join(APP.config['DOCS_FOLDER'], repo.path)
Pierre-Yves Chibon 80842e
    ticketpath = os.path.join(APP.config['TICKETS_FOLDER'], repo.path)
Pierre-Yves Chibon 0c7b30
Pierre-Yves Chibon 55a6e0
    try:
Pierre-Yves Chibon 0c7b30
        shutil.rmtree(repopath)
Pierre-Yves Chibon 0c7b30
        shutil.rmtree(docpath)
Pierre-Yves Chibon 80842e
        shutil.rmtree(ticketpath)
Pierre-Yves Chibon 55a6e0
        SESSION.commit()
Pierre-Yves Chibon 0c7b30
    except (OSError, IOError), err:
Pierre-Yves Chibon 0c7b30
        APP.logger.exception(err)
Pierre-Yves Chibon 0c7b30
        flask.flash('Could not delete the project from the system', 'error')
Pierre-Yves Chibon 55a6e0
    except SQLAlchemyError, err:  # pragma: no cover
Pierre-Yves Chibon 55a6e0
        SESSION.rollback()
Pierre-Yves Chibon 55a6e0
        APP.logger.exception(err)
Pierre-Yves Chibon 55a6e0
        flask.flash('Could not delete the project', 'error')
Pierre-Yves Chibon 55a6e0
Pierre-Yves Chibon 55a6e0
    return flask.redirect(
Pierre-Yves Chibon 55a6e0
        flask.url_for('view_user', username=flask.g.fas_user.username))
Pierre-Yves Chibon 8782bc
Pierre-Yves Chibon 8782bc
Pierre-Yves Chibon 681845
@APP.route('/<repo>/dropuser/<userid>', methods=['POST'])</userid></repo>
Pierre-Yves Chibon 681845
@APP.route('/fork/<username>/<repo>/dropuser/<userid>', methods=['POST'])</userid></repo></username>
Pierre-Yves Chibon 681845
@cla_required
Pierre-Yves Chibon 681845
def remove_user(repo, userid, username=None):
Pierre-Yves Chibon 681845
    """ Remove the specified user from the project.
Pierre-Yves Chibon 681845
    """
Pierre-Yves Chibon 681845
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 681845
Pierre-Yves Chibon 681845
    if not repo:
Pierre-Yves Chibon 681845
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 681845
Pierre-Yves Chibon 681845
    if not is_repo_admin(repo):
Pierre-Yves Chibon 681845
        flask.abort(
Pierre-Yves Chibon 681845
            403,
Pierre-Yves Chibon 9b8729
            'You are not allowed to change the users for this project')
Pierre-Yves Chibon 681845
Pierre-Yves Chibon 2286f4
    userids = [str(user.id) for user in repo.users]
Pierre-Yves Chibon 681845
Pierre-Yves Chibon 681845
    if str(userid) not in userids:
Pierre-Yves Chibon 681845
        flask.flash(
Pierre-Yves Chibon 681845
            'User does not have commit or cannot loose it right', 'error')
Pierre-Yves Chibon 681845
        return flask.redirect(
Pierre-Yves Chibon 681845
            flask.url_for(
Pierre-Yves Chibon 681845
                '.view_settings', repo=repo.name, username=username)
Pierre-Yves Chibon 681845
        )
Pierre-Yves Chibon 681845
Pierre-Yves Chibon 681845
    for user in repo.users:
Pierre-Yves Chibon 2286f4
        if str(user.id) == str(userid):
Pierre-Yves Chibon cf2ef5
            repo.users.remove(user)
Pierre-Yves Chibon 681845
            break
Pierre-Yves Chibon 71c8db
    try:
Pierre-Yves Chibon 71c8db
        SESSION.commit()
Pierre-Yves Chibon 71c8db
        progit.generate_gitolite_acls()
Pierre-Yves Chibon 71c8db
        flask.flash('User removed')
Pierre-Yves Chibon 71c8db
    except SQLAlchemyError as err:
Pierre-Yves Chibon 71c8db
        SESSION.rollback()
Pierre-Yves Chibon 71c8db
        APP.logger.exception(err)
Pierre-Yves Chibon 71c8db
        flask.flash('User could not be removed', 'error')
Pierre-Yves Chibon e1b7ed
Pierre-Yves Chibon 681845
    return flask.redirect(
Pierre-Yves Chibon 681845
        flask.url_for('.view_settings', repo=repo.name, username=username)
Pierre-Yves Chibon 681845
    )
Pierre-Yves Chibon 681845
Pierre-Yves Chibon 681845
Pierre-Yves Chibon 8782bc
@APP.route('/<repo>/adduser', methods=('GET', 'POST'))</repo>
Pierre-Yves Chibon 8782bc
@APP.route('/fork/<username>/<repo>/adduser', methods=('GET', 'POST'))</repo></username>
Pierre-Yves Chibon 8782bc
@cla_required
Pierre-Yves Chibon 8782bc
def add_user(repo, username=None):
Pierre-Yves Chibon 8782bc
    """ Add the specified user from the project.
Pierre-Yves Chibon 8782bc
    """
Pierre-Yves Chibon 8782bc
    repo = progit.lib.get_project(SESSION, repo, user=username)
Pierre-Yves Chibon 8782bc
Pierre-Yves Chibon 8782bc
    if not repo:
Pierre-Yves Chibon 8782bc
        flask.abort(404, 'Project not found')
Pierre-Yves Chibon 8782bc
Pierre-Yves Chibon 8782bc
    if not is_repo_admin(repo):
Pierre-Yves Chibon 8782bc
        flask.abort(
Pierre-Yves Chibon 8782bc
            403,
Pierre-Yves Chibon 9b8729
            'You are not allowed to add users to this project')
Pierre-Yves Chibon 8782bc
Pierre-Yves Chibon 8782bc
    form = progit.forms.AddUserForm()
Pierre-Yves Chibon 8782bc
Pierre-Yves Chibon 8782bc
    if form.validate_on_submit():
Pierre-Yves Chibon 10f22f
        try:
Pierre-Yves Chibon 10f22f
            msg = progit.lib.add_user_to_project(
Pierre-Yves Chibon 10f22f
                SESSION, repo, form.user.data)
Pierre-Yves Chibon 10f22f
            SESSION.commit()
Pierre-Yves Chibon 10f22f
            progit.generate_gitolite_acls()
Pierre-Yves Chibon 10f22f
            flask.flash(msg)
Pierre-Yves Chibon 10f22f
            return flask.redirect(
Pierre-Yves Chibon 10f22f
                flask.url_for(
Pierre-Yves Chibon 10f22f
                    '.view_settings', repo=repo.name, username=username)
Pierre-Yves Chibon 10f22f
            )
Pierre-Yves Chibon 10f22f
        except progit.exceptions.ProgitException as msg:
Pierre-Yves Chibon 71c8db
            SESSION.rollback()
Pierre-Yves Chibon 10f22f
            flask.flash(msg, 'error')
Pierre-Yves Chibon 71c8db
        except SQLAlchemyError as err:
Pierre-Yves Chibon 71c8db
            SESSION.rollback()
Pierre-Yves Chibon 71c8db
            APP.logger.exception(err)
Pierre-Yves Chibon 71c8db
            flask.flash('User could not be added', 'error')
Pierre-Yves Chibon 8782bc
Pierre-Yves Chibon 8782bc
    return flask.render_template(
Pierre-Yves Chibon 8782bc
        'add_user.html',
Pierre-Yves Chibon 8782bc
        form=form,
Pierre-Yves Chibon 8782bc
        username=username,
Pierre-Yves Chibon 8782bc
        repo=repo,
Pierre-Yves Chibon 8782bc
    )