|
Pierre-Yves Chibon |
33b534 |
# -*- coding: utf-8 -*-
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
"""
|
|
Pierre-Yves Chibon |
ddede6 |
(c) 2014 - Copyright Red Hat Inc
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
Authors:
|
|
Pierre-Yves Chibon |
ddede6 |
Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
"""
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
import flask
|
|
Pierre-Yves Chibon |
ddede6 |
import os
|
|
Pierre-Yves Chibon |
ddede6 |
from math import ceil
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
import pygit2
|
|
Pierre-Yves Chibon |
ddede6 |
from sqlalchemy.exc import SQLAlchemyError
|
|
Pierre-Yves Chibon |
ddede6 |
from pygments import highlight
|
|
Pierre-Yves Chibon |
ddede6 |
from pygments.lexers import guess_lexer
|
|
Pierre-Yves Chibon |
ddede6 |
from pygments.lexers.text import DiffLexer
|
|
Pierre-Yves Chibon |
ddede6 |
from pygments.formatters import HtmlFormatter
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
import progit.doc_utils
|
|
Pierre-Yves Chibon |
822345 |
import progit.exceptions
|
|
Pierre-Yves Chibon |
ddede6 |
import progit.lib
|
|
Pierre-Yves Chibon |
ddede6 |
import progit.forms
|
|
Pierre-Yves Chibon |
ddede6 |
from progit import APP, SESSION, LOG, cla_required
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
b6076a |
def __get_tree(repo_obj, tree, filepath, index=0, extended=False):
|
|
Pierre-Yves Chibon |
ddede6 |
''' Retrieve the entry corresponding to the provided filename in a
|
|
Pierre-Yves Chibon |
ddede6 |
given tree.
|
|
Pierre-Yves Chibon |
ddede6 |
'''
|
|
Pierre-Yves Chibon |
b6076a |
filename = filepath[index]
|
|
Pierre-Yves Chibon |
b6076a |
if isinstance(tree, pygit2.Blob): # pragma: no cover
|
|
Pierre-Yves Chibon |
b6076a |
# If we were given a blob, then let's just return it
|
|
Pierre-Yves Chibon |
ddede6 |
return (tree, None)
|
|
Pierre-Yves Chibon |
ddede6 |
cnt = 0
|
|
Pierre-Yves Chibon |
b6076a |
|
|
Pierre-Yves Chibon |
ddede6 |
for el in tree:
|
|
Pierre-Yves Chibon |
b6076a |
if el.name == filename or el.name.startswith('index'):
|
|
Pierre-Yves Chibon |
b6076a |
# If we have a folder we must go one level deeper
|
|
Pierre-Yves Chibon |
b6076a |
if el.filemode == 16384:
|
|
Pierre-Yves Chibon |
b6076a |
if (index + 1) == len(filepath):
|
|
Pierre-Yves Chibon |
b6076a |
filepath.append('')
|
|
Pierre-Yves Chibon |
b6076a |
return __get_tree(
|
|
Pierre-Yves Chibon |
b6076a |
repo_obj, repo_obj[el.oid], filepath, index=index + 1,
|
|
Pierre-Yves Chibon |
b6076a |
extended=True)
|
|
Pierre-Yves Chibon |
b6076a |
else:
|
|
Pierre-Yves Chibon |
b6076a |
return (el, tree, False)
|
|
Pierre-Yves Chibon |
b6076a |
|
|
Pierre-Yves Chibon |
b6076a |
if filename == '':
|
|
Pierre-Yves Chibon |
b6076a |
return (None, tree, extended)
|
|
Pierre-Yves Chibon |
822345 |
else:
|
|
Pierre-Yves Chibon |
b6076a |
raise progit.exceptions.FileNotFoundException(
|
|
Pierre-Yves Chibon |
b6076a |
'File %s not found' % ('/'.join(filepath),))
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
def __get_tree_and_content(repo_obj, commit, path, startswith):
|
|
Pierre-Yves Chibon |
ddede6 |
''' Return the tree and the content of the specified file. '''
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
b6076a |
(blob_or_tree, tree_obj, extended) = __get_tree(
|
|
Pierre-Yves Chibon |
b6076a |
repo_obj, commit.tree, path)
|
|
Pierre-Yves Chibon |
3b01c0 |
|
|
Pierre-Yves Chibon |
3b01c0 |
if blob_or_tree is None:
|
|
Pierre-Yves Chibon |
b6076a |
return (tree_obj, None, extended)
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
if not repo_obj[blob_or_tree.oid]:
|
|
Pierre-Yves Chibon |
b6076a |
# Not tested and no idea how to test it, but better safe than sorry
|
|
Pierre-Yves Chibon |
ddede6 |
flask.abort(404, 'File not found')
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
b6076a |
if isinstance(blob_or_tree, pygit2.TreeEntry): # Returned a file
|
|
Pierre-Yves Chibon |
ddede6 |
name, ext = os.path.splitext(blob_or_tree.name)
|
|
Pierre-Yves Chibon |
b6076a |
blob_obj = repo_obj[blob_or_tree.oid]
|
|
Pierre-Yves Chibon |
b6076a |
content = progit.doc_utils.convert_readme(blob_obj.data, ext)
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
tree = sorted(tree_obj, key=lambda x: x.filemode)
|
|
Pierre-Yves Chibon |
b6076a |
return (tree, content, extended)
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
e04c77 |
# URLs
|
|
Pierre-Yves Chibon |
c4da03 |
|
|
Pierre-Yves Chibon |
c4da03 |
|
|
Pierre-Yves Chibon |
c4da03 |
@APP.route('/<repo>/docs')</repo>
|
|
Pierre-Yves Chibon |
c4da03 |
@APP.route('/<repo>/docs/<path:filename>')</path:filename></repo>
|
|
Pierre-Yves Chibon |
c4da03 |
@APP.route('/<repo>/docs/<branchname>')</branchname></repo>
|
|
Pierre-Yves Chibon |
c4da03 |
@APP.route('/<repo>/docs/<branchname>/<path:filename>')</path:filename></branchname></repo>
|
|
Pierre-Yves Chibon |
c4da03 |
@APP.route('/fork/<username>/<repo>/docs')</repo></username>
|
|
Pierre-Yves Chibon |
c4da03 |
@APP.route('/fork/<username>/<repo>/docs/<path:filename>')</path:filename></repo></username>
|
|
Pierre-Yves Chibon |
c4da03 |
@APP.route('/fork/<username>/<repo>/docs/<branchname>')</branchname></repo></username>
|
|
Pierre-Yves Chibon |
c4da03 |
@APP.route('/fork/<username>/<repo>/docs/<branchname>/<path:filename>')</path:filename></branchname></repo></username>
|
|
Pierre-Yves Chibon |
4b7a7d |
def view_docs(repo, username=None, branchname=None, filename=None):
|
|
Pierre-Yves Chibon |
c4da03 |
""" Display the documentation
|
|
Pierre-Yves Chibon |
ddede6 |
"""
|
|
Pierre-Yves Chibon |
c4da03 |
status = flask.request.args.get('status', None)
|
|
Pierre-Yves Chibon |
c4da03 |
|
|
Pierre-Yves Chibon |
ddede6 |
repo = progit.lib.get_project(SESSION, repo, user=username)
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
if not repo:
|
|
Pierre-Yves Chibon |
ddede6 |
flask.abort(404, 'Project not found')
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
4b7a7d |
if not repo.project_docs:
|
|
Pierre-Yves Chibon |
c2f4ca |
flask.abort(404, 'No documentation found for this project')
|
|
Pierre-Yves Chibon |
c2f4ca |
|
|
Pierre-Yves Chibon |
4b7a7d |
reponame = os.path.join(APP.config['DOCS_FOLDER'], repo.path)
|
|
Pierre-Yves Chibon |
a386bc |
if not os.path.exists(reponame):
|
|
Pierre-Yves Chibon |
a386bc |
flask.flash(
|
|
Pierre-Yves Chibon |
4b7a7d |
'No docs repository could be found, please contact an admin',
|
|
Pierre-Yves Chibon |
a386bc |
'error')
|
|
Pierre-Yves Chibon |
a386bc |
return flask.redirect(flask.url_for(
|
|
Pierre-Yves Chibon |
a386bc |
'view_repo', repo=repo.name, username=username))
|
|
Pierre-Yves Chibon |
a386bc |
|
|
Pierre-Yves Chibon |
ddede6 |
repo_obj = pygit2.Repository(reponame)
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
if branchname in repo_obj.listall_branches():
|
|
Pierre-Yves Chibon |
ddede6 |
branch = repo_obj.lookup_branch(branchname)
|
|
Pierre-Yves Chibon |
ddede6 |
commit = branch.get_object()
|
|
Pierre-Yves Chibon |
ddede6 |
else:
|
|
Pierre-Yves Chibon |
ddede6 |
if not repo_obj.is_empty:
|
|
Pierre-Yves Chibon |
ddede6 |
commit = repo_obj[repo_obj.head.target]
|
|
Pierre-Yves Chibon |
ddede6 |
else:
|
|
Pierre-Yves Chibon |
ddede6 |
commit = None
|
|
Pierre-Yves Chibon |
ddede6 |
branchname = 'master'
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
content = None
|
|
Pierre-Yves Chibon |
0c352b |
tree = None
|
|
Pierre-Yves Chibon |
ddede6 |
startswith = False
|
|
Pierre-Yves Chibon |
ddede6 |
if not filename:
|
|
Pierre-Yves Chibon |
b6076a |
path = ['']
|
|
Pierre-Yves Chibon |
ddede6 |
startswith = True
|
|
Pierre-Yves Chibon |
ddede6 |
else:
|
|
Pierre-Yves Chibon |
b6076a |
path = [it for it in filename.split('/') if it]
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
if commit:
|
|
Pierre-Yves Chibon |
822345 |
try:
|
|
Pierre-Yves Chibon |
b6076a |
(tree, content, extended) = __get_tree_and_content(
|
|
Pierre-Yves Chibon |
b6076a |
repo_obj, commit, path, startswith=True)
|
|
Pierre-Yves Chibon |
b6076a |
if extended:
|
|
Pierre-Yves Chibon |
b6076a |
filename += '/'
|
|
Pierre-Yves Chibon |
b6076a |
except progit.exceptions.FileNotFoundException as err:
|
|
Pierre-Yves Chibon |
b6076a |
flask.flash(err.message, 'error')
|
|
Pierre-Yves Chibon |
ddede6 |
|
|
Pierre-Yves Chibon |
ddede6 |
return flask.render_template(
|
|
Pierre-Yves Chibon |
4b7a7d |
'docs.html',
|
|
Pierre-Yves Chibon |
75a541 |
select='docs',
|
|
Pierre-Yves Chibon |
c1f7d5 |
repo_obj=repo_obj,
|
|
Pierre-Yves Chibon |
ddede6 |
repo=repo,
|
|
Pierre-Yves Chibon |
ddede6 |
username=username,
|
|
Pierre-Yves Chibon |
ddede6 |
branchname=branchname,
|
|
Pierre-Yves Chibon |
ddede6 |
filename=filename,
|
|
Pierre-Yves Chibon |
ddede6 |
tree=tree,
|
|
Pierre-Yves Chibon |
ddede6 |
content=content,
|
|
Pierre-Yves Chibon |
ddede6 |
)
|