diff --git a/progit/static/progit.css b/progit/static/progit.css index 3873ec5..d4c6d51 100644 --- a/progit/static/progit.css +++ b/progit/static/progit.css @@ -379,7 +379,7 @@ table.list .open_by { width: 9em; } -td.noresult { +.noresult { text-align: center; font-weight: bold; } @@ -408,9 +408,10 @@ td.noresult { } .issue_comment > header, -.issue_comment > form > header { +.issue_comment > form > header, +.file_content > .buttons +{ border-radius: 10px 10px 0 0; - background: #ccc; padding: .5em; border-bottom: 1px solid rgba(237, 237, 237, 0.4); @@ -454,3 +455,43 @@ td.noresult { width: 100%; padding: .5em; } + +.buttons { + padding: 0; + list-style-type: none; + text-align: right; + /*padding: .2em .5em 1em;*/ + margin: 0; +} + +.buttons li { + display: inline-block; + padding-left: .5em; +} + +.button { + display: inline-block; + color: white; + background: #0066cc; + border-radius: 3px; + padding: .2em .5em; + background-image: -webkit-linear-gradient(top, #0066cc, #34609f); + background-image: -moz-linear-gradient(top, #0066cc, #34609f); + background-image: -o-linear-gradient(top, #0066cc, #34609f); + background-image: linear-gradient(to bottom, #0066cc, #34609f); + -webkit-box-shadow: inset 0 1px rgba(255, 255, 255, 0.5), 0 0 2px rgba(0, 0, 0, 0.2); + box-shadow: inset 0 1px rgba(255, 255, 255, 0.5), 0 0 2px rgba(0, 0, 0, 0.2); +} + +.button:hover { + background-image: linear-gradient(to bottom, #34609f, #0066cc); +} + +a.button:visited, a.button:hover { + color: white; +} + +.file_content { + border: 1px solid rgba(237, 237, 237, 0.4); + border-radius: 10px 10px 0 0; +} diff --git a/progit/templates/file.html b/progit/templates/file.html index 09e6af0..cf691b5 100644 --- a/progit/templates/file.html +++ b/progit/templates/file.html @@ -25,10 +25,26 @@ {% if content %} - {% if output_type=='file' %} - {% autoescape false %} - {{ content | format_loc}} - {% endautoescape %} + {% if output_type == 'file' or output_type == 'binary' or output_type == 'image' %} +
+ + {% if output_type=='file' %} + {% autoescape false %} + {{ content | format_loc}} + {% endautoescape %} + {% elif output_type == 'binary' or output_type == 'image' %} +

Binary files cannot be rendered.
Please view the raw version

+ {% endif %} +
{% else %}

Tree

diff --git a/progit/ui/repo.py b/progit/ui/repo.py index f01c152..c43b781 100644 --- a/progit/ui/repo.py +++ b/progit/ui/repo.py @@ -20,6 +20,9 @@ from pygments.lexers import guess_lexer from pygments.lexers.text import DiffLexer from pygments.formatters import HtmlFormatter +import mimetypes +import chardet + import progit.exceptions import progit.lib import progit.forms @@ -283,8 +286,6 @@ def view_log(repo, branchname=None, username=None): @APP.route('//blob//') -@APP.route('//blob//') -@APP.route('/fork///blob//') @APP.route('/fork///blob//') def view_file(repo, identifier, filename, username=None): """ Displays the content of a file or a tree for the specified repo. @@ -318,14 +319,22 @@ def view_file(repo, identifier, filename, username=None): content = repo_obj[content.oid] if isinstance(content, pygit2.Blob): - content = highlight( - content.data, - guess_lexer(content.data), - HtmlFormatter( - noclasses=True, - style="tango",) - ) - output_type = 'file' + if content.is_binary: + ext = filename[filename.rfind('.'):] + if ext in ('.gif', '.png', '.bmp', '.tif', '.tiff', '.jpg', + '.jpeg', '.ppm', '.pnm', '.pbm', '.pgm', '.webp', '.ico'): + output_type = 'image' + else: + output_type = 'binary' + else: + content = highlight( + content.data, + guess_lexer(content.data), + HtmlFormatter( + noclasses=True, + style="tango",) + ) + output_type = 'file' else: content = sorted(content, key=lambda x: x.filemode) output_type = 'tree' @@ -342,6 +351,57 @@ def view_file(repo, identifier, filename, username=None): ) +@APP.route('//raw//') +@APP.route('/fork///raw//') +def view_raw_file(repo, identifier, filename, username=None): + """ Displays the raw content of a file for the specified repo. + """ + repo = progit.lib.get_project(SESSION, repo, user=username) + + if not repo: + flask.abort(404, 'Project not found') + + reponame = os.path.join(APP.config['GIT_FOLDER'], repo.path) + if repo.is_fork: + reponame = os.path.join(APP.config['FORK_FOLDER'], repo.path) + repo_obj = pygit2.Repository(reponame) + + if identifier in repo_obj.listall_branches(): + branch = repo_obj.lookup_branch(identifier) + commit = branch.get_object() + else: + try: + commit = repo_obj.get(identifier) + except ValueError: + # If it's not a commit id then it's part of the filename + commit = repo_obj[repo_obj.head.target] + + content = __get_file_in_tree(repo_obj, commit.tree, filename.split('/')) + if not content: + flask.abort(404, 'File not found') + + mimetype, encoding = mimetypes.guess_type(filename) + data = repo_obj[content.oid].data + + if not mimetype and data[:2] == '#!': + mimetype = 'text/plain' + + if not mimetype: + if '\0' in data: + mimetype = 'application/octet-stream' + else: + mimetype = 'text/plain' + + if mimetype.startswith('text/') and not encoding: + encoding = chardet.detect(data)['encoding'] + + headers = {'Content-Type': mimetype} + if encoding: + headers['Content-Encoding'] = encoding + + return (data, 200, headers) + + @APP.route('//') @APP.route('/fork///') def view_commit(repo, commitid, username=None):