|
Pierre-Yves Chibon |
33b534 |
# -*- 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 |
47950c |
import os
|
|
Pierre-Yves Chibon |
47950c |
from math import ceil
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
47950c |
import pygit2
|
|
Pierre-Yves Chibon |
47950c |
from sqlalchemy.exc import SQLAlchemyError
|
|
Pierre-Yves Chibon |
47950c |
from pygments import highlight
|
|
Pierre-Yves Chibon |
47950c |
from pygments.lexers import guess_lexer
|
|
Pierre-Yves Chibon |
47950c |
from pygments.lexers.text import DiffLexer
|
|
Pierre-Yves Chibon |
47950c |
from pygments.formatters import HtmlFormatter
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
ccbeb3 |
import mimetypes
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
47950c |
import progit.doc_utils
|
|
Pierre-Yves Chibon |
47950c |
import progit.lib
|
|
Pierre-Yves Chibon |
47950c |
import progit.forms
|
|
Pierre-Yves Chibon |
0dbb10 |
from progit import (APP, SESSION, LOG, __get_file_in_tree, cla_required,
|
|
Pierre-Yves Chibon |
c3d937 |
is_repo_admin, authenticated)
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
e04c77 |
# URLs
|
|
Pierre-Yves Chibon |
556a8e |
|
|
Pierre-Yves Chibon |
0a5613 |
@APP.route('/<repo>/issue/<int:issueid>/update', methods=['GET', 'POST'])</int:issueid></repo>
|
|
Pierre-Yves Chibon |
ea16af |
@APP.route('/fork/<username>/<repo>/issue/<int:issueid>/update',</int:issueid></repo></username>
|
|
Pierre-Yves Chibon |
0a5613 |
methods=['GET', 'POST'])
|
|
Pierre-Yves Chibon |
0a5613 |
@cla_required
|
|
Pierre-Yves Chibon |
ea16af |
def update_issue(repo, issueid, username=None):
|
|
Pierre-Yves Chibon |
556a8e |
''' Add a comment to an issue. '''
|
|
Pierre-Yves Chibon |
47950c |
repo = progit.lib.get_project(SESSION, repo, user=username)
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
0a5613 |
if flask.request.method == 'GET':
|
|
Pierre-Yves Chibon |
0a5613 |
flask.flash('Invalid method: GET', 'error')
|
|
Pierre-Yves Chibon |
0a5613 |
return flask.redirect(flask.url_for(
|
|
Pierre-Yves Chibon |
0a5613 |
'view_issue', username=username, repo=repo.name, issueid=issueid))
|
|
Pierre-Yves Chibon |
0a5613 |
|
|
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 |
556a8e |
if not repo.issue_tracker:
|
|
Pierre-Yves Chibon |
556a8e |
flask.abort(404, 'No issue tracker found for this project')
|
|
Pierre-Yves Chibon |
556a8e |
|
|
Pierre-Yves Chibon |
d054da |
issue = progit.lib.search_issues(SESSION, repo, issueid=issueid)
|
|
Pierre-Yves Chibon |
556a8e |
|
|
Pierre-Yves Chibon |
1d6527 |
if issue is None or issue.project != repo:
|
|
Pierre-Yves Chibon |
556a8e |
flask.abort(404, 'Issue not found')
|
|
Pierre-Yves Chibon |
556a8e |
|
|
Pierre-Yves Chibon |
a0c229 |
if issue.private and not is_repo_admin(repo) \
|
|
Pierre-Yves Chibon |
ca45e3 |
and (
|
|
Pierre-Yves Chibon |
ca45e3 |
not authenticated() or
|
|
Pierre-Yves Chibon |
ca45e3 |
not issue.user.user == flask.g.fas_user.username):
|
|
Pierre-Yves Chibon |
a0c229 |
flask.abort(
|
|
Pierre-Yves Chibon |
a0c229 |
403, 'This issue is private and you are not allowed to view it')
|
|
Pierre-Yves Chibon |
a0c229 |
|
|
Pierre-Yves Chibon |
ea16af |
status = progit.lib.get_issue_statuses(SESSION)
|
|
Pierre-Yves Chibon |
ea16af |
form = progit.forms.UpdateIssueForm(status=status)
|
|
Pierre-Yves Chibon |
ea16af |
|
|
Pierre-Yves Chibon |
47950c |
if form.validate_on_submit():
|
|
Pierre-Yves Chibon |
556a8e |
comment = form.comment.data
|
|
Pierre-Yves Chibon |
a33982 |
try:
|
|
Pierre-Yves Chibon |
a33982 |
depends = [
|
|
Pierre-Yves Chibon |
a33982 |
int(depend.strip())
|
|
Pierre-Yves Chibon |
a33982 |
for depend in form.depends.data.split(',')
|
|
Pierre-Yves Chibon |
a33982 |
if depend.strip()]
|
|
Pierre-Yves Chibon |
a33982 |
except ValueError:
|
|
Pierre-Yves Chibon |
a33982 |
depends = []
|
|
Pierre-Yves Chibon |
a33982 |
|
|
Pierre-Yves Chibon |
a33982 |
try:
|
|
Pierre-Yves Chibon |
a33982 |
blocks = [
|
|
Pierre-Yves Chibon |
a33982 |
int(block.strip())
|
|
Pierre-Yves Chibon |
a33982 |
for block in form.blocks.data.split(',')
|
|
Pierre-Yves Chibon |
a33982 |
if block.strip()]
|
|
Pierre-Yves Chibon |
a33982 |
except ValueError:
|
|
Pierre-Yves Chibon |
a33982 |
blocks = []
|
|
Pierre-Yves Chibon |
a33982 |
|
|
Pierre-Yves Chibon |
ea16af |
assignee = form.assignee.data
|
|
Pierre-Yves Chibon |
ea16af |
new_status = form.status.data
|
|
Pierre-Yves Chibon |
ea16af |
tags = [
|
|
Pierre-Yves Chibon |
ea16af |
tag.strip()
|
|
Pierre-Yves Chibon |
ea16af |
for tag in form.tag.data.split(',')
|
|
Pierre-Yves Chibon |
ea16af |
if tag.strip()]
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
47950c |
try:
|
|
Pierre-Yves Chibon |
a33982 |
|
|
Pierre-Yves Chibon |
a33982 |
# New comment
|
|
Pierre-Yves Chibon |
ea16af |
if comment:
|
|
Pierre-Yves Chibon |
ea16af |
message = progit.lib.add_issue_comment(
|
|
Pierre-Yves Chibon |
3df87b |
SESSION,
|
|
Pierre-Yves Chibon |
3df87b |
issue=issue,
|
|
Pierre-Yves Chibon |
ea16af |
comment=comment,
|
|
Pierre-Yves Chibon |
3df87b |
user=flask.g.fas_user.username,
|
|
Pierre-Yves Chibon |
3df87b |
ticketfolder=APP.config['TICKETS_FOLDER'],
|
|
Pierre-Yves Chibon |
3df87b |
)
|
|
Pierre-Yves Chibon |
ea8d98 |
SESSION.commit()
|
|
Pierre-Yves Chibon |
07add5 |
if message:
|
|
Pierre-Yves Chibon |
07add5 |
flask.flash(message)
|
|
Pierre-Yves Chibon |
4a8cb4 |
|
|
Pierre-Yves Chibon |
a33982 |
# Adjust (add/remove) tags
|
|
Pierre-Yves Chibon |
214a1e |
messages = progit.lib.update_tags_issue(
|
|
Pierre-Yves Chibon |
214a1e |
SESSION, issue, tags,
|
|
Pierre-Yves Chibon |
214a1e |
username=flask.g.fas_user.username,
|
|
Pierre-Yves Chibon |
214a1e |
ticketfolder=APP.config['TICKETS_FOLDER'])
|
|
Pierre-Yves Chibon |
214a1e |
for message in messages:
|
|
Pierre-Yves Chibon |
214a1e |
flask.flash(message)
|
|
Pierre-Yves Chibon |
ea16af |
|
|
Pierre-Yves Chibon |
a33982 |
# Assign or update assignee of the ticket
|
|
Pierre-Yves Chibon |
985245 |
message = progit.lib.add_issue_assignee(
|
|
Pierre-Yves Chibon |
985245 |
SESSION,
|
|
Pierre-Yves Chibon |
985245 |
issue=issue,
|
|
Pierre-Yves Chibon |
985245 |
assignee=assignee or None,
|
|
Pierre-Yves Chibon |
985245 |
user=flask.g.fas_user.username,
|
|
Pierre-Yves Chibon |
985245 |
ticketfolder=APP.config['TICKETS_FOLDER'],)
|
|
Pierre-Yves Chibon |
985245 |
if message:
|
|
Pierre-Yves Chibon |
985245 |
SESSION.commit()
|
|
Pierre-Yves Chibon |
985245 |
flask.flash(message)
|
|
Pierre-Yves Chibon |
ea16af |
|
|
Pierre-Yves Chibon |
a33982 |
# Update status
|
|
Pierre-Yves Chibon |
21f51e |
if new_status in status:
|
|
Pierre-Yves Chibon |
ea16af |
message = progit.lib.edit_issue(
|
|
Pierre-Yves Chibon |
840cbe |
SESSION,
|
|
Pierre-Yves Chibon |
ea16af |
issue=issue,
|
|
Pierre-Yves Chibon |
ea16af |
status=new_status,
|
|
Pierre-Yves Chibon |
ea16af |
ticketfolder=APP.config['TICKETS_FOLDER'],
|
|
Pierre-Yves Chibon |
ea16af |
)
|
|
Pierre-Yves Chibon |
4a8cb4 |
SESSION.commit()
|
|
Pierre-Yves Chibon |
07add5 |
if message:
|
|
Pierre-Yves Chibon |
07add5 |
flask.flash(message)
|
|
Pierre-Yves Chibon |
a33982 |
|
|
Pierre-Yves Chibon |
a33982 |
# Update ticket this one depends on
|
|
Pierre-Yves Chibon |
a86f36 |
messages = progit.lib.update_dependency_issue(
|
|
Pierre-Yves Chibon |
f49685 |
SESSION, repo, issue, depends,
|
|
Pierre-Yves Chibon |
a86f36 |
username=flask.g.fas_user.username,
|
|
Pierre-Yves Chibon |
a86f36 |
ticketfolder=APP.config['TICKETS_FOLDER'])
|
|
Pierre-Yves Chibon |
a86f36 |
for message in messages:
|
|
Pierre-Yves Chibon |
a86f36 |
flask.flash(message)
|
|
Pierre-Yves Chibon |
a33982 |
|
|
Pierre-Yves Chibon |
a33982 |
# Update ticket(s) depending on this one
|
|
Pierre-Yves Chibon |
a86f36 |
messages = progit.lib.update_blocked_issue(
|
|
Pierre-Yves Chibon |
f49685 |
SESSION, repo, issue, blocks,
|
|
Pierre-Yves Chibon |
a86f36 |
username=flask.g.fas_user.username,
|
|
Pierre-Yves Chibon |
a86f36 |
ticketfolder=APP.config['TICKETS_FOLDER'])
|
|
Pierre-Yves Chibon |
a86f36 |
for message in messages:
|
|
Pierre-Yves Chibon |
a86f36 |
flask.flash(message)
|
|
Pierre-Yves Chibon |
a33982 |
|
|
Pierre-Yves Chibon |
c8aec7 |
except progit.exceptions.ProgitException, err:
|
|
Pierre-Yves Chibon |
c8aec7 |
SESSION.rollback()
|
|
Pierre-Yves Chibon |
4713b8 |
flask.flash(err.message, 'error')
|
|
Pierre-Yves Chibon |
4a8cb4 |
except SQLAlchemyError, err: # pragma: no cover
|
|
Pierre-Yves Chibon |
4a8cb4 |
SESSION.rollback()
|
|
Pierre-Yves Chibon |
ea16af |
APP.logger.exception(err)
|
|
Pierre-Yves Chibon |
ea16af |
flask.flash(str(err), 'error')
|
|
Pierre-Yves Chibon |
4a8cb4 |
|
|
Pierre-Yves Chibon |
4a8cb4 |
return flask.redirect(flask.url_for(
|
|
Pierre-Yves Chibon |
4a8cb4 |
'view_issue', username=username, repo=repo.name, issueid=issueid))
|
|
Pierre-Yves Chibon |
fccfc5 |
|
|
Pierre-Yves Chibon |
fccfc5 |
|
|
Pierre-Yves Chibon |
de0eea |
@APP.route('/<repo>/tag/<tag>/edit', methods=('GET', 'POST'))</tag></repo>
|
|
Pierre-Yves Chibon |
de0eea |
@APP.route('/fork/<username>/<repo>/tag/<tag>/edit', methods=('GET', 'POST'))</tag></repo></username>
|
|
Pierre-Yves Chibon |
de0eea |
@cla_required
|
|
Pierre-Yves Chibon |
de0eea |
def edit_tag(repo, tag, username=None):
|
|
Pierre-Yves Chibon |
de0eea |
""" Edit the specified tag of a project.
|
|
Pierre-Yves Chibon |
de0eea |
"""
|
|
Pierre-Yves Chibon |
de0eea |
repo = progit.lib.get_project(SESSION, repo, user=username)
|
|
Pierre-Yves Chibon |
de0eea |
|
|
Pierre-Yves Chibon |
de0eea |
if not repo:
|
|
Pierre-Yves Chibon |
de0eea |
flask.abort(404, 'Project not found')
|
|
Pierre-Yves Chibon |
de0eea |
|
|
Pierre-Yves Chibon |
de0eea |
if not is_repo_admin(repo):
|
|
Pierre-Yves Chibon |
de0eea |
flask.abort(
|
|
Pierre-Yves Chibon |
de0eea |
403,
|
|
Pierre-Yves Chibon |
de0eea |
'You are not allowed to add users to this project')
|
|
Pierre-Yves Chibon |
de0eea |
|
|
Pierre-Yves Chibon |
de0eea |
form = progit.forms.AddIssueTagForm()
|
|
Pierre-Yves Chibon |
de0eea |
if form.validate_on_submit():
|
|
Pierre-Yves Chibon |
de0eea |
new_tag = form.tag.data
|
|
Pierre-Yves Chibon |
de0eea |
|
|
Pierre-Yves Chibon |
725bd6 |
msgs = progit.lib.edit_issue_tags(
|
|
Pierre-Yves Chibon |
725bd6 |
SESSION, repo, tag, new_tag,
|
|
Pierre-Yves Chibon |
725bd6 |
ticketfolder=APP.config['TICKETS_FOLDER']
|
|
Pierre-Yves Chibon |
725bd6 |
)
|
|
Pierre-Yves Chibon |
de0eea |
|
|
Pierre-Yves Chibon |
be12c2 |
try:
|
|
Pierre-Yves Chibon |
be12c2 |
SESSION.commit()
|
|
Pierre-Yves Chibon |
be12c2 |
for msg in msgs:
|
|
Pierre-Yves Chibon |
be12c2 |
flask.flash(msg)
|
|
Pierre-Yves Chibon |
be12c2 |
except SQLAlchemyError, err: # pragma: no cover
|
|
Pierre-Yves Chibon |
be12c2 |
SESSION.rollback()
|
|
Pierre-Yves Chibon |
be12c2 |
LOG.error(err)
|
|
Pierre-Yves Chibon |
e04c77 |
flask.flash('Could not edit tag: %s' % tag, 'error')
|
|
Pierre-Yves Chibon |
de0eea |
|
|
Pierre-Yves Chibon |
de0eea |
return flask.redirect(flask.url_for(
|
|
Pierre-Yves Chibon |
de0eea |
'.view_settings', repo=repo.name, username=username)
|
|
Pierre-Yves Chibon |
de0eea |
)
|
|
Pierre-Yves Chibon |
de0eea |
|
|
Pierre-Yves Chibon |
de0eea |
return flask.render_template(
|
|
Pierre-Yves Chibon |
de0eea |
'edit_tag.html',
|
|
Pierre-Yves Chibon |
de0eea |
form=form,
|
|
Pierre-Yves Chibon |
de0eea |
username=username,
|
|
Pierre-Yves Chibon |
de0eea |
repo=repo,
|
|
Pierre-Yves Chibon |
de0eea |
tag=tag,
|
|
Pierre-Yves Chibon |
de0eea |
)
|
|
Pierre-Yves Chibon |
de0eea |
|
|
Pierre-Yves Chibon |
048944 |
|
|
Pierre-Yves Chibon |
048944 |
@APP.route('/<repo>/droptag/', methods=['POST'])</repo>
|
|
Pierre-Yves Chibon |
048944 |
@APP.route('/fork/<username>/<repo>/droptag/', methods=['POST'])</repo></username>
|
|
Pierre-Yves Chibon |
048944 |
@cla_required
|
|
Pierre-Yves Chibon |
048944 |
def remove_tag(repo, username=None):
|
|
Pierre-Yves Chibon |
048944 |
""" Remove the specified tag from the project.
|
|
Pierre-Yves Chibon |
048944 |
"""
|
|
Pierre-Yves Chibon |
048944 |
repo = progit.lib.get_project(SESSION, repo, user=username)
|
|
Pierre-Yves Chibon |
048944 |
|
|
Pierre-Yves Chibon |
048944 |
if not repo:
|
|
Pierre-Yves Chibon |
048944 |
flask.abort(404, 'Project not found')
|
|
Pierre-Yves Chibon |
048944 |
|
|
Pierre-Yves Chibon |
048944 |
if not is_repo_admin(repo):
|
|
Pierre-Yves Chibon |
048944 |
flask.abort(
|
|
Pierre-Yves Chibon |
048944 |
403,
|
|
Pierre-Yves Chibon |
048944 |
'You are not allowed to change the users for this project')
|
|
Pierre-Yves Chibon |
048944 |
|
|
Pierre-Yves Chibon |
048944 |
form = progit.forms.AddIssueTagForm()
|
|
Pierre-Yves Chibon |
048944 |
if form.validate_on_submit():
|
|
Pierre-Yves Chibon |
048944 |
tags = form.tag.data
|
|
Pierre-Yves Chibon |
048944 |
tags = [tag.strip() for tag in tags.split(',')]
|
|
Pierre-Yves Chibon |
048944 |
|
|
Pierre-Yves Chibon |
b4ce96 |
msgs = progit.lib.remove_tags(
|
|
Pierre-Yves Chibon |
b4ce96 |
SESSION, repo, tags,
|
|
Pierre-Yves Chibon |
b4ce96 |
ticketfolder=APP.config['TICKETS_FOLDER']
|
|
Pierre-Yves Chibon |
b4ce96 |
)
|
|
Pierre-Yves Chibon |
048944 |
|
|
Pierre-Yves Chibon |
7aa682 |
try:
|
|
Pierre-Yves Chibon |
7aa682 |
SESSION.commit()
|
|
Pierre-Yves Chibon |
7aa682 |
for msg in msgs:
|
|
Pierre-Yves Chibon |
7aa682 |
flask.flash(msg)
|
|
Pierre-Yves Chibon |
7aa682 |
except SQLAlchemyError, err: # pragma: no cover
|
|
Pierre-Yves Chibon |
7aa682 |
SESSION.rollback()
|
|
Pierre-Yves Chibon |
7aa682 |
LOG.error(err)
|
|
Pierre-Yves Chibon |
7aa682 |
flask.flash(
|
|
Pierre-Yves Chibon |
7aa682 |
'Could not remove tag: %s' % ','.join(tags), 'error')
|
|
Pierre-Yves Chibon |
048944 |
|
|
Pierre-Yves Chibon |
048944 |
return flask.redirect(
|
|
Pierre-Yves Chibon |
048944 |
flask.url_for('.view_settings', repo=repo.name, username=username)
|
|
Pierre-Yves Chibon |
048944 |
)
|
|
Pierre-Yves Chibon |
048944 |
|
|
Pierre-Yves Chibon |
e04c77 |
|
|
Pierre-Yves Chibon |
556a8e |
@APP.route('/<repo>/issues')</repo>
|
|
Pierre-Yves Chibon |
556a8e |
@APP.route('/fork/<username>/<repo>/issues')</repo></username>
|
|
Pierre-Yves Chibon |
556a8e |
def view_issues(repo, username=None):
|
|
Pierre-Yves Chibon |
556a8e |
""" List all issues associated to a repo
|
|
Pierre-Yves Chibon |
47950c |
"""
|
|
Pierre-Yves Chibon |
556a8e |
status = flask.request.args.get('status', None)
|
|
Pierre-Yves Chibon |
a8ec77 |
tags = flask.request.args.getlist('tags')
|
|
Pierre-Yves Chibon |
a8ec77 |
tags = [tag.strip() for tag in tags if tag.strip()]
|
|
Pierre-Yves Chibon |
1f7038 |
assignee = flask.request.args.get('assignee', None)
|
|
Pierre-Yves Chibon |
2604db |
author = flask.request.args.get('author', None)
|
|
Pierre-Yves Chibon |
556a8e |
|
|
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 |
if not repo.issue_tracker:
|
|
Pierre-Yves Chibon |
47950c |
flask.abort(404, 'No issue tracker found for this project')
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
c8c669 |
# Hide private tickets
|
|
Pierre-Yves Chibon |
c8c669 |
private = False
|
|
Pierre-Yves Chibon |
c8c669 |
# If user is authenticated, show him/her his/her private tickets
|
|
Pierre-Yves Chibon |
c8c669 |
if authenticated():
|
|
Pierre-Yves Chibon |
c8c669 |
private = flask.g.fas_user.username
|
|
Pierre-Yves Chibon |
c8c669 |
# If user is repo admin, show all tickets included the private ones
|
|
Pierre-Yves Chibon |
c8c669 |
if is_repo_admin(repo):
|
|
Pierre-Yves Chibon |
c8c669 |
private = None
|
|
Pierre-Yves Chibon |
c8c669 |
|
|
Pierre-Yves Chibon |
936256 |
oth_issues = None
|
|
Pierre-Yves Chibon |
556a8e |
if status is not None:
|
|
Pierre-Yves Chibon |
556a8e |
if status.lower() == 'closed':
|
|
Pierre-Yves Chibon |
3b7b2b |
issues = progit.lib.search_issues(
|
|
Pierre-Yves Chibon |
1f7038 |
SESSION,
|
|
Pierre-Yves Chibon |
1f7038 |
repo,
|
|
Pierre-Yves Chibon |
1f7038 |
closed=True,
|
|
Pierre-Yves Chibon |
1f7038 |
tags=tags,
|
|
Pierre-Yves Chibon |
1f7038 |
assignee=assignee,
|
|
Pierre-Yves Chibon |
2604db |
author=author,
|
|
Pierre-Yves Chibon |
c8c669 |
private=private,
|
|
Pierre-Yves Chibon |
1f7038 |
)
|
|
Pierre-Yves Chibon |
936256 |
oth_issues = progit.lib.search_issues(
|
|
Pierre-Yves Chibon |
936256 |
SESSION,
|
|
Pierre-Yves Chibon |
936256 |
repo,
|
|
Pierre-Yves Chibon |
936256 |
status='Open',
|
|
Pierre-Yves Chibon |
936256 |
tags=tags,
|
|
Pierre-Yves Chibon |
936256 |
assignee=assignee,
|
|
Pierre-Yves Chibon |
936256 |
author=author,
|
|
Pierre-Yves Chibon |
936256 |
private=private,
|
|
Pierre-Yves Chibon |
936256 |
count=True,
|
|
Pierre-Yves Chibon |
936256 |
)
|
|
Pierre-Yves Chibon |
556a8e |
else:
|
|
Pierre-Yves Chibon |
3b7b2b |
issues = progit.lib.search_issues(
|
|
Pierre-Yves Chibon |
1f7038 |
SESSION,
|
|
Pierre-Yves Chibon |
1f7038 |
repo,
|
|
Pierre-Yves Chibon |
1f7038 |
status=status,
|
|
Pierre-Yves Chibon |
1f7038 |
tags=tags,
|
|
Pierre-Yves Chibon |
1f7038 |
assignee=assignee,
|
|
Pierre-Yves Chibon |
2604db |
author=author,
|
|
Pierre-Yves Chibon |
c8c669 |
private=private,
|
|
Pierre-Yves Chibon |
1f7038 |
)
|
|
Pierre-Yves Chibon |
936256 |
|
|
Pierre-Yves Chibon |
556a8e |
else:
|
|
Pierre-Yves Chibon |
3b7b2b |
issues = progit.lib.search_issues(
|
|
Pierre-Yves Chibon |
2604db |
SESSION, repo, status='Open', tags=tags, assignee=assignee,
|
|
Pierre-Yves Chibon |
c8c669 |
author=author, private=private)
|
|
Pierre-Yves Chibon |
936256 |
oth_issues = progit.lib.search_issues(
|
|
Pierre-Yves Chibon |
936256 |
SESSION, repo, closed=True, tags=tags, assignee=assignee,
|
|
Pierre-Yves Chibon |
936256 |
author=author, private=private, count=True)
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
15f6e9 |
tag_list = progit.lib.get_tags_of_project(SESSION, repo)
|
|
Pierre-Yves Chibon |
15f6e9 |
|
|
Pierre-Yves Chibon |
556a8e |
return flask.render_template(
|
|
Pierre-Yves Chibon |
556a8e |
'issues.html',
|
|
Pierre-Yves Chibon |
556a8e |
select='issues',
|
|
Pierre-Yves Chibon |
556a8e |
repo=repo,
|
|
Pierre-Yves Chibon |
556a8e |
username=username,
|
|
Pierre-Yves Chibon |
a8ec77 |
tag_list=tag_list,
|
|
Pierre-Yves Chibon |
556a8e |
status=status,
|
|
Pierre-Yves Chibon |
556a8e |
issues=issues,
|
|
Pierre-Yves Chibon |
936256 |
oth_issues=oth_issues,
|
|
Pierre-Yves Chibon |
15f6e9 |
tags=tags,
|
|
Pierre-Yves Chibon |
a8ec77 |
assignee=assignee,
|
|
Pierre-Yves Chibon |
a8ec77 |
author=author,
|
|
Pierre-Yves Chibon |
556a8e |
)
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
556a8e |
|
|
Pierre-Yves Chibon |
556a8e |
@APP.route('/<repo>/new_issue', methods=('GET', 'POST'))</repo>
|
|
Pierre-Yves Chibon |
556a8e |
@APP.route('/fork/<username>/<repo>/new_issue', methods=('GET', 'POST'))</repo></username>
|
|
Pierre-Yves Chibon |
556a8e |
@cla_required
|
|
Pierre-Yves Chibon |
556a8e |
def new_issue(repo, username=None):
|
|
Pierre-Yves Chibon |
556a8e |
""" Create a new issue
|
|
Pierre-Yves Chibon |
556a8e |
"""
|
|
Pierre-Yves Chibon |
556a8e |
repo = progit.lib.get_project(SESSION, repo, user=username)
|
|
Pierre-Yves Chibon |
556a8e |
|
|
Pierre-Yves Chibon |
556a8e |
if repo is None:
|
|
Pierre-Yves Chibon |
556a8e |
flask.abort(404, 'Project not found')
|
|
Pierre-Yves Chibon |
556a8e |
|
|
Pierre-Yves Chibon |
c5a9a2 |
status = progit.lib.get_issue_statuses(SESSION)
|
|
Pierre-Yves Chibon |
c5a9a2 |
form = progit.forms.IssueForm(status=status)
|
|
Pierre-Yves Chibon |
47950c |
if form.validate_on_submit():
|
|
Pierre-Yves Chibon |
47950c |
title = form.title.data
|
|
Pierre-Yves Chibon |
c5a9a2 |
content = form.issue_content.data
|
|
Pierre-Yves Chibon |
a5090c |
private = form.private.data
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
47950c |
try:
|
|
Pierre-Yves Chibon |
556a8e |
message = progit.lib.new_issue(
|
|
Pierre-Yves Chibon |
47950c |
SESSION,
|
|
Pierre-Yves Chibon |
556a8e |
repo=repo,
|
|
Pierre-Yves Chibon |
47950c |
title=title,
|
|
Pierre-Yves Chibon |
47950c |
content=content,
|
|
Pierre-Yves Chibon |
a5090c |
private=private or False,
|
|
Pierre-Yves Chibon |
556a8e |
user=flask.g.fas_user.username,
|
|
Pierre-Yves Chibon |
a34835 |
ticketfolder=APP.config['TICKETS_FOLDER'],
|
|
Pierre-Yves Chibon |
47950c |
)
|
|
Pierre-Yves Chibon |
47950c |
SESSION.commit()
|
|
Pierre-Yves Chibon |
47950c |
flask.flash(message)
|
|
Pierre-Yves Chibon |
556a8e |
return flask.redirect(flask.url_for(
|
|
Pierre-Yves Chibon |
a3258a |
'view_issues', username=username, repo=repo.name))
|
|
Pierre-Yves Chibon |
47950c |
except progit.exceptions.ProgitException, err:
|
|
Pierre-Yves Chibon |
47950c |
flask.flash(str(err), 'error')
|
|
Pierre-Yves Chibon |
47950c |
except SQLAlchemyError, err: # pragma: no cover
|
|
Pierre-Yves Chibon |
47950c |
SESSION.rollback()
|
|
Pierre-Yves Chibon |
47950c |
flask.flash(str(err), 'error')
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
47950c |
return flask.render_template(
|
|
Pierre-Yves Chibon |
47950c |
'new_issue.html',
|
|
Pierre-Yves Chibon |
47950c |
select='issues',
|
|
Pierre-Yves Chibon |
47950c |
form=form,
|
|
Pierre-Yves Chibon |
47950c |
repo=repo,
|
|
Pierre-Yves Chibon |
47950c |
username=username,
|
|
Pierre-Yves Chibon |
47950c |
)
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
fa46bf |
@APP.route('/<repo>/issue/<int:issueid>')</int:issueid></repo>
|
|
Pierre-Yves Chibon |
fa46bf |
@APP.route('/fork/<username>/<repo>/issue/<int:issueid>')</int:issueid></repo></username>
|
|
Pierre-Yves Chibon |
556a8e |
def view_issue(repo, issueid, username=None):
|
|
Pierre-Yves Chibon |
47950c |
""" List all issues associated to a repo
|
|
Pierre-Yves Chibon |
47950c |
"""
|
|
Pierre-Yves Chibon |
556a8e |
|
|
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 |
if not repo.issue_tracker:
|
|
Pierre-Yves Chibon |
47950c |
flask.abort(404, 'No issue tracker found for this project')
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
d054da |
issue = progit.lib.search_issues(SESSION, repo, issueid=issueid)
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
362d6b |
if issue is None or issue.project != repo:
|
|
Pierre-Yves Chibon |
47950c |
flask.abort(404, 'Issue not found')
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
b9a6f7 |
if issue.private and not is_repo_admin(repo) \
|
|
Pierre-Yves Chibon |
ca45e3 |
and (
|
|
Pierre-Yves Chibon |
ca45e3 |
not authenticated() or
|
|
Pierre-Yves Chibon |
ca45e3 |
not issue.user.user == flask.g.fas_user.username):
|
|
Pierre-Yves Chibon |
b9a6f7 |
flask.abort(
|
|
Pierre-Yves Chibon |
b9a6f7 |
403, 'This issue is private and you are not allowed to view it')
|
|
Pierre-Yves Chibon |
b9a6f7 |
|
|
Pierre-Yves Chibon |
47950c |
status = progit.lib.get_issue_statuses(SESSION)
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
ea16af |
form = progit.forms.UpdateIssueForm(status=status)
|
|
Pierre-Yves Chibon |
059d5c |
form.status.data = issue.status
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
47950c |
return flask.render_template(
|
|
Pierre-Yves Chibon |
47950c |
'issue.html',
|
|
Pierre-Yves Chibon |
47950c |
select='issues',
|
|
Pierre-Yves Chibon |
47950c |
repo=repo,
|
|
Pierre-Yves Chibon |
47950c |
username=username,
|
|
Pierre-Yves Chibon |
47950c |
issue=issue,
|
|
Pierre-Yves Chibon |
c156b6 |
issueid=issueid,
|
|
Pierre-Yves Chibon |
47950c |
form=form,
|
|
Pierre-Yves Chibon |
424d2c |
repo_admin=is_repo_admin(repo),
|
|
Pierre-Yves Chibon |
47950c |
)
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
47950c |
|
|
Pierre-Yves Chibon |
32cbdc |
@APP.route('/<repo>/issue/<int:issueid>/edit', methods=('GET', 'POST'))</int:issueid></repo>
|
|
Pierre-Yves Chibon |
32cbdc |
@APP.route('/fork/<username>/<repo>/issue/<int:issueid>/edit',</int:issueid></repo></username>
|
|
Pierre-Yves Chibon |
f9a5d2 |
methods=('GET', 'POST'))
|
|
Pierre-Yves Chibon |
556a8e |
@cla_required
|
|
Pierre-Yves Chibon |
556a8e |
def edit_issue(repo, issueid, username=None):
|
|
Pierre-Yves Chibon |
556a8e |
""" Edit the specified issue
|
|
Pierre-Yves Chibon |
556a8e |
"""
|
|
Pierre-Yves Chibon |
f9a5d2 |
repo = progit.lib.get_project(SESSION, repo, user=username)
|
|
Pierre-Yves Chibon |
f9a5d2 |
|
|
Pierre-Yves Chibon |
f9a5d2 |
if repo is None:
|
|
Pierre-Yves Chibon |
f9a5d2 |
flask.abort(404, 'Project not found')
|
|
Pierre-Yves Chibon |
f9a5d2 |
|
|
Pierre-Yves Chibon |
f9a5d2 |
if not repo.issue_tracker:
|
|
Pierre-Yves Chibon |
f9a5d2 |
flask.abort(404, 'No issue tracker found for this project')
|
|
Pierre-Yves Chibon |
f9a5d2 |
|
|
Pierre-Yves Chibon |
0dbb10 |
if not is_repo_admin(repo):
|
|
Pierre-Yves Chibon |
0dbb10 |
flask.abort(
|
|
Pierre-Yves Chibon |
0dbb10 |
403, 'You are not allowed to edit issues for this project')
|
|
Pierre-Yves Chibon |
0dbb10 |
|
|
Pierre-Yves Chibon |
d054da |
issue = progit.lib.search_issues(SESSION, repo, issueid=issueid)
|
|
Pierre-Yves Chibon |
f9a5d2 |
|
|
Pierre-Yves Chibon |
1d6527 |
if issue is None or issue.project != repo:
|
|
Pierre-Yves Chibon |
f9a5d2 |
flask.abort(404, 'Issue not found')
|
|
Pierre-Yves Chibon |
f9a5d2 |
|
|
Pierre-Yves Chibon |
556a8e |
status = progit.lib.get_issue_statuses(SESSION)
|
|
Pierre-Yves Chibon |
556a8e |
form = progit.forms.IssueForm(status=status)
|
|
Pierre-Yves Chibon |
f9a5d2 |
if form.validate_on_submit():
|
|
Pierre-Yves Chibon |
556a8e |
title = form.title.data
|
|
Pierre-Yves Chibon |
824f5d |
content = form.issue_content.data
|
|
Pierre-Yves Chibon |
556a8e |
status = form.status.data
|
|
Pierre-Yves Chibon |
be1ede |
private = form.private.data
|
|
Pierre-Yves Chibon |
f9a5d2 |
|
|
Pierre-Yves Chibon |
f9a5d2 |
try:
|
|
Pierre-Yves Chibon |
556a8e |
message = progit.lib.edit_issue(
|
|
Pierre-Yves Chibon |
f9a5d2 |
SESSION,
|
|
Pierre-Yves Chibon |
f9a5d2 |
issue=issue,
|
|
Pierre-Yves Chibon |
556a8e |
title=title,
|
|
Pierre-Yves Chibon |
556a8e |
content=content,
|
|
Pierre-Yves Chibon |
556a8e |
status=status,
|
|
Pierre-Yves Chibon |
a34835 |
ticketfolder=APP.config['TICKETS_FOLDER'],
|
|
Pierre-Yves Chibon |
be1ede |
private=private,
|
|
Pierre-Yves Chibon |
f9a5d2 |
)
|
|
Pierre-Yves Chibon |
f9a5d2 |
SESSION.commit()
|
|
Pierre-Yves Chibon |
f9a5d2 |
flask.flash(message)
|
|
Pierre-Yves Chibon |
556a8e |
url = flask.url_for(
|
|
Pierre-Yves Chibon |
556a8e |
'view_issue', username=username,
|
|
Pierre-Yves Chibon |
6bf823 |
repo=repo.name, issueid=issueid)
|
|
Pierre-Yves Chibon |
556a8e |
return flask.redirect(url)
|
|
Pierre-Yves Chibon |
f9a5d2 |
except SQLAlchemyError, err: # pragma: no cover
|
|
Pierre-Yves Chibon |
f9a5d2 |
SESSION.rollback()
|
|
Pierre-Yves Chibon |
f9a5d2 |
flask.flash(str(err), 'error')
|
|
Pierre-Yves Chibon |
556a8e |
elif flask.request.method == 'GET':
|
|
Pierre-Yves Chibon |
556a8e |
form.title.data = issue.title
|
|
Pierre-Yves Chibon |
824f5d |
form.issue_content.data = issue.content
|
|
Pierre-Yves Chibon |
556a8e |
form.status.data = issue.status
|
|
Pierre-Yves Chibon |
b93312 |
form.private.data = issue.private
|
|
Pierre-Yves Chibon |
f9a5d2 |
|
|
Pierre-Yves Chibon |
556a8e |
return flask.render_template(
|
|
Pierre-Yves Chibon |
556a8e |
'new_issue.html',
|
|
Pierre-Yves Chibon |
556a8e |
select='issues',
|
|
Pierre-Yves Chibon |
556a8e |
type='edit',
|
|
Pierre-Yves Chibon |
556a8e |
form=form,
|
|
Pierre-Yves Chibon |
556a8e |
repo=repo,
|
|
Pierre-Yves Chibon |
556a8e |
username=username,
|
|
Pierre-Yves Chibon |
556a8e |
issue=issue,
|
|
Pierre-Yves Chibon |
32cbdc |
issueid=issueid,
|
|
Pierre-Yves Chibon |
556a8e |
)
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
@APP.route('/<repo>/issue/<int:issueid>/upload', methods=['POST'])</int:issueid></repo>
|
|
Pierre-Yves Chibon |
ccbeb3 |
@APP.route('/fork/<username>/<repo>/issue/<int:issueid>/upload',</int:issueid></repo></username>
|
|
Pierre-Yves Chibon |
ccbeb3 |
methods=['POST'])
|
|
Pierre-Yves Chibon |
ccbeb3 |
@cla_required
|
|
Pierre-Yves Chibon |
ccbeb3 |
def upload_issue(repo, issueid, username=None):
|
|
Pierre-Yves Chibon |
ccbeb3 |
''' Upload a file to a ticket.
|
|
Pierre-Yves Chibon |
ccbeb3 |
'''
|
|
Pierre-Yves Chibon |
ccbeb3 |
repo = progit.lib.get_project(SESSION, repo, user=username)
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
if repo is None:
|
|
Pierre-Yves Chibon |
ccbeb3 |
flask.abort(404, 'Project not found')
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
if not repo.issue_tracker:
|
|
Pierre-Yves Chibon |
ccbeb3 |
flask.abort(404, 'No issue tracker found for this project')
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
if not is_repo_admin(repo):
|
|
Pierre-Yves Chibon |
ccbeb3 |
flask.abort(
|
|
Pierre-Yves Chibon |
ccbeb3 |
403, 'You are not allowed to edit issues for this project')
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
issue = progit.lib.search_issues(SESSION, repo, issueid=issueid)
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
if issue is None or issue.project != repo:
|
|
Pierre-Yves Chibon |
ccbeb3 |
flask.abort(404, 'Issue not found')
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
form = progit.forms.UploadFileForm()
|
|
Pierre-Yves Chibon |
ccbeb3 |
# pylint: disable=E1101
|
|
Pierre-Yves Chibon |
ccbeb3 |
if form.validate_on_submit():
|
|
Pierre-Yves Chibon |
ccbeb3 |
filestream = flask.request.files['filestream']
|
|
Pierre-Yves Chibon |
ccbeb3 |
new_filename = progit.lib.git.add_file_to_git(
|
|
Pierre-Yves Chibon |
ccbeb3 |
repo=repo,
|
|
Pierre-Yves Chibon |
ccbeb3 |
issue=issue,
|
|
Pierre-Yves Chibon |
ccbeb3 |
ticketfolder=APP.config['TICKETS_FOLDER'],
|
|
Pierre-Yves Chibon |
ccbeb3 |
user=flask.g.fas_user,
|
|
Pierre-Yves Chibon |
ccbeb3 |
filename=filestream.filename,
|
|
Pierre-Yves Chibon |
ccbeb3 |
filestream=filestream.stream,
|
|
Pierre-Yves Chibon |
ccbeb3 |
)
|
|
Pierre-Yves Chibon |
ccbeb3 |
return flask.jsonify({
|
|
Pierre-Yves Chibon |
ccbeb3 |
'output': 'ok',
|
|
Pierre-Yves Chibon |
ccbeb3 |
'filename': new_filename.split('-', 1)[1],
|
|
Pierre-Yves Chibon |
ccbeb3 |
'filelocation': flask.url_for(
|
|
Pierre-Yves Chibon |
ccbeb3 |
'view_issue_raw_file',
|
|
Pierre-Yves Chibon |
ccbeb3 |
repo=repo.name,
|
|
Pierre-Yves Chibon |
ccbeb3 |
username=username,
|
|
Pierre-Yves Chibon |
ccbeb3 |
filename=new_filename,
|
|
Pierre-Yves Chibon |
ccbeb3 |
)
|
|
Pierre-Yves Chibon |
ccbeb3 |
})
|
|
Pierre-Yves Chibon |
ccbeb3 |
else:
|
|
Pierre-Yves Chibon |
ccbeb3 |
return flask.jsonify({'output': 'notok'})
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
@APP.route('/<repo>/issue/raw/<path:filename>')</path:filename></repo>
|
|
Pierre-Yves Chibon |
ccbeb3 |
@APP.route('/fork/<username>/<repo>/issue/raw/<path:filename>')</path:filename></repo></username>
|
|
Pierre-Yves Chibon |
ccbeb3 |
def view_issue_raw_file(repo, filename=None, username=None):
|
|
Pierre-Yves Chibon |
ccbeb3 |
""" Displays the raw content of a file of a commit for the specified
|
|
Pierre-Yves Chibon |
ccbeb3 |
ticket repo.
|
|
Pierre-Yves Chibon |
ccbeb3 |
"""
|
|
Pierre-Yves Chibon |
ccbeb3 |
repo = progit.lib.get_project(SESSION, repo, user=username)
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
if not repo:
|
|
Pierre-Yves Chibon |
ccbeb3 |
flask.abort(404, 'Project not found')
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
reponame = os.path.join(APP.config['TICKETS_FOLDER'], repo.path)
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
repo_obj = pygit2.Repository(reponame)
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
if repo_obj.is_empty:
|
|
Pierre-Yves Chibon |
ccbeb3 |
flask.abort(404, 'Empty repo cannot have a file')
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
branch = repo_obj.lookup_branch('master')
|
|
Pierre-Yves Chibon |
ccbeb3 |
commit = branch.get_object()
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
mimetype = None
|
|
Pierre-Yves Chibon |
ccbeb3 |
encoding = None
|
|
Pierre-Yves Chibon |
ccbeb3 |
if filename:
|
|
Pierre-Yves Chibon |
ccbeb3 |
content = __get_file_in_tree(
|
|
Pierre-Yves Chibon |
ccbeb3 |
repo_obj, commit.tree, filename.split('/'))
|
|
Pierre-Yves Chibon |
ccbeb3 |
if not content or isinstance(content, pygit2.Tree):
|
|
Pierre-Yves Chibon |
ccbeb3 |
flask.abort(404, 'File not found')
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
mimetype, encoding = mimetypes.guess_type(filename)
|
|
Pierre-Yves Chibon |
ccbeb3 |
data = repo_obj[content.oid].data
|
|
Pierre-Yves Chibon |
ccbeb3 |
else:
|
|
Pierre-Yves Chibon |
ccbeb3 |
if commit.parents:
|
|
Pierre-Yves Chibon |
ccbeb3 |
diff = commit.tree.diff_to_tree()
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
parent = repo_obj.revparse_single('%s^' % identifier)
|
|
Pierre-Yves Chibon |
ccbeb3 |
diff = repo_obj.diff(parent, commit)
|
|
Pierre-Yves Chibon |
ccbeb3 |
else:
|
|
Pierre-Yves Chibon |
ccbeb3 |
# First commit in the repo
|
|
Pierre-Yves Chibon |
ccbeb3 |
diff = commit.tree.diff_to_tree(swap=True)
|
|
Pierre-Yves Chibon |
ccbeb3 |
data = diff.patch
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
if not mimetype and data[:2] == '#!':
|
|
Pierre-Yves Chibon |
ccbeb3 |
mimetype = 'text/plain'
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
if not mimetype:
|
|
Pierre-Yves Chibon |
ccbeb3 |
if '\0' in data:
|
|
Pierre-Yves Chibon |
ccbeb3 |
mimetype = 'application/octet-stream'
|
|
Pierre-Yves Chibon |
ccbeb3 |
else:
|
|
Pierre-Yves Chibon |
ccbeb3 |
mimetype = 'text/plain'
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
if mimetype.startswith('text/') and not encoding:
|
|
Pierre-Yves Chibon |
ccbeb3 |
encoding = chardet.detect(ktc.to_bytes(data))['encoding']
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
headers = {'Content-Type': mimetype}
|
|
Pierre-Yves Chibon |
ccbeb3 |
if encoding:
|
|
Pierre-Yves Chibon |
ccbeb3 |
headers['Content-Encoding'] = encoding
|
|
Pierre-Yves Chibon |
ccbeb3 |
|
|
Pierre-Yves Chibon |
ccbeb3 |
return (data, 200, headers)
|