From d80e3b8494d09393935b278813359945b497e8dd Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 03 2015 09:04:52 +0000 Subject: [PATCH 1/9] Rework the doc server - Render HTML if the git repo contains HTML - Convert the REST or Markdown to HTML and render it - Render css and js with the correct mimetype --- diff --git a/pagure/docs_server.py b/pagure/docs_server.py index 90da7fd..792dee6 100644 --- a/pagure/docs_server.py +++ b/pagure/docs_server.py @@ -54,7 +54,8 @@ def __get_tree(repo_obj, tree, filepath, index=0, extended=False): return (tree, None, None) for element in tree: - if element.name == filename or element.name.startswith('index'): + if element.name == filename or \ + (not filename and element.name.startswith('index')): # If we have a folder we must go one level deeper if element.filemode == 16384: if (index + 1) == len(filepath): @@ -233,16 +234,10 @@ def view_forks(repo, username=None): # The actual logic of the doc server @APP.route('//') -@APP.route('/') @APP.route('//') -@APP.route('//') -@APP.route('///') @APP.route('/fork///') -@APP.route('/fork//') @APP.route('/fork///') -@APP.route('/fork///') -@APP.route('/fork////') -def view_docs(repo, username=None, branchname=None, filename=None): +def view_docs(repo, username=None, filename=None): """ Display the documentation """ @@ -260,15 +255,12 @@ def view_docs(repo, username=None, branchname=None, filename=None): repo_obj = pygit2.Repository(reponame) - if branchname in repo_obj.listall_branches(): - branch = repo_obj.lookup_branch(branchname) - commit = branch.get_object() + + if not repo_obj.is_empty: + commit = repo_obj[repo_obj.head.target] else: - if not repo_obj.is_empty: - commit = repo_obj[repo_obj.head.target] - else: - commit = None - branchname = 'master' + flask.abort(404, 'No content found is the repository') + branchname = 'master' content = None tree = None @@ -287,16 +279,12 @@ def view_docs(repo, username=None, branchname=None, filename=None): except pagure.exceptions.FileNotFoundException as err: flask.flash(err.message, 'error') - return flask.render_template( - 'docs.html', - select='docs', - repo_obj=repo_obj, - repo=repo, - username=username, - branchname=branchname, - filename=filename, - tree=tree, - content=content, - safe=safe, - nologin=True, - ) + mimetype = None + if not filename: + pass + elif filename.endswith('.css'): + mimetype = 'text/css' + elif filename.endswith('.js'): + mimetype = 'application/javascript' + + return flask.Response(content, mimetype=mimetype) From 5e75eec27cfda04574161b4d943a82bab24aee11 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 03 2015 09:05:34 +0000 Subject: [PATCH 2/9] Simplify the doc server No need for all the boiler plate code we were using before to go from the project to the doc and vice-versa since we do not use the templates anymore. --- diff --git a/pagure/docs_server.py b/pagure/docs_server.py index 792dee6..62293b6 100644 --- a/pagure/docs_server.py +++ b/pagure/docs_server.py @@ -95,144 +95,6 @@ def __get_tree_and_content(repo_obj, commit, path): return (tree, content, safe, extended) -# Jinja filter required - -@APP.template_filter('markdown') -def markdown_filter(text): - """ Template filter converting a string into html content using the - markdown library. - """ - return pagure.lib.text2markdown(text, extended=False) - - -# Placeholder to allow re-using pagure's templates -@APP.route('/') -def index(): - ''' Redirects to the front page of this pagure instance. ''' - return flask.redirect(APP.config['APP_URL']) - - -@APP.route('/users/') -def view_users(): - ''' Redirects to the list of users on this pagure instance. ''' - root_url = APP.config['APP_URL'] - if root_url.endswith('/'): - root_url = root_url[:-1] - return flask.redirect(root_url + '/users/') - - -@APP.route('/groups/') -def group_lists(): - ''' Redirects to the list of groups on this pagure instance. ''' - root_url = APP.config['APP_URL'] - if root_url.endswith('/'): - root_url = root_url[:-1] - return flask.redirect(root_url + '/groups/') - - -@APP.route('/new/') -def new_project(): - ''' Redirects to the page to create a new project on this pagure - instance. - ''' - root_url = APP.config['APP_URL'] - if root_url.endswith('/'): - root_url = root_url[:-1] - return flask.redirect(root_url + '/new/') - - -@APP.route('/repo//') -@APP.route('/repo/fork///') -def view_repo(repo, username=None): - ''' Redirects to the overview page of this project. ''' - root_url = APP.config['APP_URL'] - if root_url.endswith('/'): - root_url = root_url[:-1] - return flask.redirect( - root_url + flask.url_for('.view_docs', repo=repo, username=username)) - - -@APP.route('//issues/') -@APP.route('/fork///issues/') -def view_issues(repo, username=None): - ''' Redirects to the page listing all issues of this project. ''' - root_url = APP.config['APP_URL'] - if root_url.endswith('/'): - root_url = root_url[:-1] - return flask.redirect( - root_url - + flask.url_for('.view_docs', repo=repo, username=username) - + '/issues/') - - -@APP.route('//commits/') -@APP.route('/fork///commits/') -def view_commits(repo, username=None): - ''' Redirects to the page listing all commits of this project. ''' - root_url = APP.config['APP_URL'] - if root_url.endswith('/'): - root_url = root_url[:-1] - return flask.redirect( - root_url - + flask.url_for('.view_docs', repo=repo, username=username) - + '/commits/') - - -@APP.route('//tree/') -@APP.route('/fork///tree/') -def view_tree(repo, username=None): - ''' Redirects to the page displaying the tree of files of this project. - ''' - root_url = APP.config['APP_URL'] - if root_url.endswith('/'): - root_url = root_url[:-1] - return flask.redirect( - root_url - + flask.url_for('.view_docs', repo=repo, username=username) - + '/tree/') - - -@APP.route('//tags/') -@APP.route('/fork///tags/') -def view_tags(repo, username=None): - ''' Redirects to the page listing all tags of this project. ''' - root_url = APP.config['APP_URL'] - if root_url.endswith('/'): - root_url = root_url[:-1] - return flask.redirect( - root_url - + flask.url_for('.view_docs', repo=repo, username=username) - + '/tags/') - - -@APP.route('//pull-requests/') -@APP.route('/fork///pull-requests/') -def request_pulls(repo, username=None): - ''' Redirects to the page listing all pull-requests of this project. ''' - root_url = APP.config['APP_URL'] - if root_url.endswith('/'): - root_url = root_url[:-1] - return flask.redirect( - root_url - + flask.url_for('.view_docs', repo=repo, username=username) - + '/pull-requests/') - - -@APP.route('//forks/') -@APP.route('/fork///forks/') -def view_forks(repo, username=None): - ''' Redirects to the page listing all forks of this project. ''' - root_url = APP.config['APP_URL'] - if root_url.endswith('/'): - root_url = root_url[:-1] - return flask.redirect( - root_url - + flask.url_for('.view_docs', repo=repo, username=username) - + '/forks/') - - -# The actual logic of the doc server - @APP.route('//') @APP.route('//') @APP.route('/fork///') From 2c035ab94fa73f181233c3513d198398ec3aa71d Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 03 2015 12:00:18 +0000 Subject: [PATCH 3/9] Adjust the docs template to just include the documentation via an iframe --- diff --git a/pagure/templates/docs.html b/pagure/templates/docs.html index 1393d81..f9ba528 100644 --- a/pagure/templates/docs.html +++ b/pagure/templates/docs.html @@ -6,90 +6,15 @@ {% block repo %} -

Docs

- -{% if repo_obj and repo_obj.is_empty %} - -
-

This repo is brand new!

- -

If you already have a git repo:

-
-      git remote add origin {{ config.get('GIT_URL_SSH') }}docs/{{ repo.fullname }}.git
-      git push -u origin master
-    
- -

If you have not created your git repo yet:

-
-      git clone {{ config.get('GIT_URL_SSH') }}docs/{{ repo.fullname }}.git
-      cd {{ repo.name }}
-      touch README.rst
-      git add README.rst
-      git commit -m "Add README file"
-      git push -u origin master
-    
- -
- -{% else %} -

- - {{ branchname }}/{% if filename %}{% - for file in filename.split('/') %} - {% if loop.first %} - {% set path = file %} - {% else %} - {% set path = path + '/' + file %} - {% endif %} - {% if loop.index != loop.length %}{{ file }}/{% else %}{{ file }}{% endif %} - {% endfor %}{% endif %} -

- - {% if tree %} -
- -
- {% endif %} - - {% if content %} -
- {{ content |safe }} -
- {% endif %} - - - -{% endif %} + {% endblock %} From 4699f0cb27d2f3280a67e522b58d86def44ca343 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 03 2015 12:00:38 +0000 Subject: [PATCH 4/9] Re-introduce the view_docs endpoint This time it is just rendering a template that includes the project's documentation on the doc server via an iframe --- diff --git a/pagure/templates/repo_master.html b/pagure/templates/repo_master.html index d906ab6..a60eccf 100644 --- a/pagure/templates/repo_master.html +++ b/pagure/templates/repo_master.html @@ -41,8 +41,7 @@ {% if config['DOC_APP_URL'] and repo.settings.get('project_documentation', True) %}
  • - Docs + Docs
  • {% endif %} diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index fc66057..55073ca 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -1359,3 +1359,19 @@ def delete_branch(repo, branchname, username=None): return flask.redirect( flask.url_for('view_repo', repo=repo, username=username)) + + +@APP.route('/docs//') +@APP.route('/docs//') +@APP.route('/docs/fork///') +@APP.route('/docs/fork///') +def view_docs(repo, username=None, filename=None): + """ Display the documentation + """ + repo_obj = pagure.lib.get_project(SESSION, repo, user=username) + return flask.render_template( + 'docs.html', + repo=repo_obj, + username=username, + filename=filename, + ) From 7b96f4011cac8bcd3cf9b01116fce6d1b33438e6 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 03 2015 12:58:12 +0000 Subject: [PATCH 5/9] Adjust the doc server for empty doc repo or repo without index page In the first case, we raise a 404 error, in the later case, we list all the files and folder present in the repo --- diff --git a/pagure/docs_server.py b/pagure/docs_server.py index 62293b6..ea5450d 100644 --- a/pagure/docs_server.py +++ b/pagure/docs_server.py @@ -43,6 +43,24 @@ APP.logger.addHandler(SHANDLER) LOG = APP.logger +TMPL_HTML = ''' + + + + + + + +{content} + + +''' + def __get_tree(repo_obj, tree, filepath, index=0, extended=False): ''' Retrieve the entry corresponding to the provided filename in a @@ -149,4 +167,13 @@ def view_docs(repo, username=None, filename=None): elif filename.endswith('.js'): mimetype = 'application/javascript' + if not filename and not content: + if not len(tree): + flask.abort(404, 'No content found is the repository') + html = '
  • ' + for el in tree: + html += ''.format(el.name) + html += '
  • ' + content = TMPL_HTML.format(content=html) + return flask.Response(content, mimetype=mimetype) From 50167749c9592fd6c81be1d8847fc8b4b3b49b83 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 03 2015 13:21:50 +0000 Subject: [PATCH 6/9] Accounts for doc repo having sub-folders and display folders with a trailing slash --- diff --git a/pagure/docs_server.py b/pagure/docs_server.py index ea5450d..4c0e3d5 100644 --- a/pagure/docs_server.py +++ b/pagure/docs_server.py @@ -167,12 +167,16 @@ def view_docs(repo, username=None, filename=None): elif filename.endswith('.js'): mimetype = 'application/javascript' - if not filename and not content: + if not content: if not len(tree): flask.abort(404, 'No content found is the repository') html = '
  • ' for el in tree: - html += ''.format(el.name) + name = el.name + # Append a trailing '/' to the folders + if el.filemode == 16384: + name += '/' + html += ''.format(el.name, name) html += '
  • ' content = TMPL_HTML.format(content=html) From 8c40831f84ff30306208108ecae057161af4392d Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 03 2015 13:29:44 +0000 Subject: [PATCH 7/9] Tree can sometime be None in which case len() won't work --- diff --git a/pagure/docs_server.py b/pagure/docs_server.py index 4c0e3d5..dad385e 100644 --- a/pagure/docs_server.py +++ b/pagure/docs_server.py @@ -168,7 +168,7 @@ def view_docs(repo, username=None, filename=None): mimetype = 'application/javascript' if not content: - if not len(tree): + if not tree or not len(tree): flask.abort(404, 'No content found is the repository') html = '
  • ' for el in tree: From 832b32fb9b44de6cf182cbc724dc8015160ea6a6 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 03 2015 13:29:57 +0000 Subject: [PATCH 8/9] Adjust the unit-tests for the new behavior of the doc server --- diff --git a/tests/test_pagure_flask_docs.py b/tests/test_pagure_flask_docs.py index c0767e4..7037358 100644 --- a/tests/test_pagure_flask_docs.py +++ b/tests/test_pagure_flask_docs.py @@ -93,11 +93,7 @@ class PagureFlaskDocstests(tests.Modeltests): tests.create_projects_git(os.path.join(tests.HERE, 'docs')) output = self.app.get('/test/docs') - self.assertEqual(output.status_code, 200) - self.assertTrue('

    Docs

    ' in output.data) - self.assertTrue('

    This repo is brand new!

    ' in output.data) - self.assertTrue( - 'git clone ssh://git@pagure.org/docs/test.git' in output.data) + self.assertEqual(output.status_code, 404) repo.settings = {'project_documentation': False} self.session.add(repo) @@ -113,11 +109,7 @@ class PagureFlaskDocstests(tests.Modeltests): os.path.join(tests.HERE, 'docs', 'test.git'), bare=True) output = self.app.get('/test/docs') - self.assertEqual(output.status_code, 200) - self.assertTrue('

    Docs

    ' in output.data) - self.assertTrue('

    This repo is brand new!

    ' in output.data) - self.assertTrue( - 'git clone ssh://git@pagure.org/docs/test.git' in output.data) + self.assertEqual(output.status_code, 404) # forked doc repo docrepo = os.path.join(tests.HERE, 'docs', 'test', 'test.git') @@ -162,54 +154,33 @@ class PagureFlaskDocstests(tests.Modeltests): # Now check the UI output = self.app.get('/test/docs') - self.assertEqual(output.status_code, 200) - self.assertTrue('

    Docs

    ' in output.data) - self.assertFalse('

    This repo is brand new!

    ' in output.data) - self.assertTrue( - '' in output.data) - self.assertTrue( - '' in output.data) + self.assertEqual(output.status_code, 404) - output = self.app.get('/test/master/sources') + output = self.app.get('/test/sources') self.assertEqual(output.status_code, 200) - self.assertTrue('

    Docs

    ' in output.data) - self.assertTrue('
    ' in output.data) + self.assertEqual('
    foo\n bar
    ', output.data) - output = self.app.get('/test/master/folder1/folder2') + output = self.app.get('/test/folder1/folder2') self.assertEqual(output.status_code, 200) - self.assertTrue('

    Docs

    ' in output.data) self.assertTrue( - '
  • \n ' - '' + '
  • ' in output.data) - output = self.app.get('/test/master/folder1/folder2/test_file') + output = self.app.get('/test/folder1/folder2/test_file') self.assertEqual(output.status_code, 200) - self.assertTrue('

    Docs

    ' in output.data) - self.assertTrue( - '
    \n
    row1\nrow2\n'
    -            'row3
    \n
    ' in output.data) + self.assertEqual('
    row1\nrow2\nrow3
    ', output.data) - output = self.app.get('/test/master/folder1') + output = self.app.get('/test/folder1') self.assertEqual(output.status_code, 200) - self.assertTrue('

    Docs

    ' in output.data) self.assertTrue( - '
  • \n ' - '' + '
  • ' in output.data) - output = self.app.get('/test/master/folder1/foo') - self.assertEqual(output.status_code, 200) - self.assertTrue('

    Docs

    ' in output.data) - self.assertTrue( - '
  • File folder1/foo not found
  • ' - in output.data) + output = self.app.get('/test/folder1/foo') + self.assertEqual(output.status_code, 404) - output = self.app.get('/test/master/folder1/foo/folder2') - self.assertEqual(output.status_code, 200) - self.assertTrue( - '
  • File folder1/foo/folder2 not found
  • ' - in output.data) + output = self.app.get('/test/folder1/foo/folder2') + self.assertEqual(output.status_code, 404) if __name__ == '__main__': From 3386465680a6596320489c36a213f3080b3f0abf Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Aug 03 2015 19:52:24 +0000 Subject: [PATCH 9/9] '.md' is also a common extension for markdown files --- diff --git a/pagure/doc_utils.py b/pagure/doc_utils.py index 6765063..3b6914b 100644 --- a/pagure/doc_utils.py +++ b/pagure/doc_utils.py @@ -93,7 +93,7 @@ def convert_readme(content, ext, view_file_url=None): if ext and ext in ['.rst']: safe = True output = convert_doc(content, view_file_url) - elif ext and ext in ['.mk']: + elif ext and ext in ['.mk', '.md']: output = markdown.markdown(content) safe = True elif not ext or (ext and ext in ['.text', '.txt']):