Klaus Demo ~jonashaag/klaus / 04d307c
Refactoring Jonas Haag 6 years ago
7 changed file(s) with 72 addition(s) and 69 deletion(s). Raw diff Collapse all Expand all
1515 }
1616
1717 def __init__(self, repo_paths, site_name, use_smarthttp):
18 self.repos = [FancyRepo(path) for path in repo_paths]
19 self.repo_map = dict((repo.name, repo) for repo in self.repos)
18 """(See `make_app` for parameter descriptions.)"""
19 repo_objs = [FancyRepo(path) for path in repo_paths]
20 self.repos = dict((repo.name, repo) for repo in repo_objs)
2021 self.site_name = site_name
2122 self.use_smarthttp = use_smarthttp
2223
2526 self.setup_routes()
2627
2728 def create_jinja_environment(self):
28 """ Called by Flask.__init__ """
29 """Called by Flask.__init__"""
2930 env = super(Klaus, self).create_jinja_environment()
3031 for func in [
3132 'force_unicode',
6465 self.add_url_rule(rule, view_func=getattr(views, endpoint))
6566
6667
67 def make_app(repos, site_name, use_smarthttp=False, htdigest_file=None,
68 def make_app(repo_paths, site_name, use_smarthttp=False, htdigest_file=None,
6869 require_browser_auth=False, disable_push=False, unauthenticated_push=False):
6970 """
7071 Returns a WSGI app with all the features (smarthttp, authentication)
7172 already patched in.
7273
73 :param repos: List of paths of repositories to serve.
74 :param repo_paths: List of paths of repositories to serve.
7475 :param site_name: Name of the Web site (e.g. "John Doe's Git Repositories")
7576 :param use_smarthttp: Enable Git Smart HTTP mode, which makes it possible to
7677 pull from the served repositories. If `htdigest_file` is set as well,
9596 raise ValueError("'htdigest_file' set without 'use_smarthttp' or 'require_browser_auth'")
9697
9798 app = Klaus(
98 repos,
99 repo_paths,
99100 site_name,
100101 use_smarthttp,
101102 )
104105 if use_smarthttp:
105106 # `path -> Repo` mapping for Dulwich's web support
106107 dulwich_backend = dulwich.server.DictBackend(
107 dict(('/'+repo.name, repo) for repo in app.repos)
108 dict(('/'+name, repo) for name, repo in app.repos.items())
108109 )
109110 # Dulwich takes care of all Git related requests/URLs
110111 # and passes through everything else to klaus
146146
147147 # Skip "no newline at end of file" markers
148148 line = next(lineiter)
149 if line == "\ No newline at end of file":
149 if line == r"\ No newline at end of file":
150150 lines[-1]['no_newline'] = True
151151 line = next(lineiter)
152152
0 from pygments import highlight
1 from pygments.lexers import get_lexer_for_filename, \
2 guess_lexer, ClassNotFound, TextLexer
3 from pygments.formatters import HtmlFormatter
4
5 from klaus import markup
6
7
8 class KlausDefaultFormatter(HtmlFormatter):
9 def __init__(self, **kwargs):
10 HtmlFormatter.__init__(self, linenos='table', lineanchors='L',
11 linespans='L', anchorlinenos=True, **kwargs)
12
13 def _format_lines(self, tokensource):
14 for tag, line in HtmlFormatter._format_lines(self, tokensource):
15 if tag == 1:
16 # sourcecode line
17 line = '<span class=line>%s</span>' % line
18 yield tag, line
19
20
21 def pygmentize(code, filename, render_markup):
22 """Render code using Pygments, markup (markdown, rst, ...) using the
23 corresponding renderer, if available.
24
25 :param code: the program code to highlight, str
26 :param filename: name of the source file the code is taken from, str
27 :param render_markup: whether to render markup if possible, bool
28 """
29 if render_markup and markup.can_render(filename):
30 return markup.render(filename, code)
31
32 try:
33 lexer = get_lexer_for_filename(filename, code)
34 except ClassNotFound:
35 try:
36 lexer = guess_lexer(code)
37 except ClassNotFound:
38 lexer = TextLexer()
39
40 return highlight(code, lexer, KlausFormatter())
6969 """Return a list of ref names that begin with `prefix`, ordered by the
7070 time they have been committed to last.
7171 """
72 refs = self.refs.as_dict(encode_for_git(prefix))
73 if exclude:
74 refs.pop(prefix + exclude, None)
75
7672 def get_commit_time(refname):
7773 obj = self[refs[refname]]
7874 if isinstance(obj, dulwich.objects.Tag):
7975 return obj.tag_time
8076 return obj.commit_time
8177
82 return [decode_from_git(ref) for ref in
83 sorted(refs.keys(), key=get_commit_time, reverse=True)]
78 refs = self.refs.as_dict(encode_for_git(prefix))
79 if exclude:
80 refs.pop(prefix + exclude, None)
81 sorted_names = sorted(refs.keys(), key=get_commit_time, reverse=True)
82 return [decode_from_git(ref) for ref in sorted_names]
8483
8584 def get_branch_names(self, exclude=None):
8685 """Return a list of branch names of this repo, ordered by the time they
33 from io import BytesIO
44 from contextlib import closing
55
6 from klaus.utils import encode_for_git, decode_from_git
6 from klaus.utils import decode_from_git
77
88
99 class ListBytesIO(object):
1010 except ImportError:
1111 chardet = None
1212
13 from pygments import highlight
14 from pygments.lexers import get_lexer_for_filename, guess_lexer, ClassNotFound, TextLexer
15 from pygments.formatters import HtmlFormatter
16
1713 from humanize import naturaltime
18
19 from klaus import markup
2014
2115
2216 class SubUri(object):
5145 environ['wsgi.url_scheme'] = environ['HTTP_X_SCHEME']
5246
5347 return self.app(environ, start_response)
54
55
56 class KlausFormatter(HtmlFormatter):
57 def __init__(self):
58 HtmlFormatter.__init__(self, linenos='table', lineanchors='L',
59 linespans='L', anchorlinenos=True)
60
61 def _format_lines(self, tokensource):
62 for tag, line in HtmlFormatter._format_lines(self, tokensource):
63 if tag == 1:
64 # sourcecode line
65 line = '<span class=line>%s</span>' % line
66 yield tag, line
67
68
69 def pygmentize(code, filename=None, render_markup=True):
70 """Render code using Pygments, markup (markdown, rst, ...) using the
71 corresponding renderer, if available.
72 """
73 if render_markup and markup.can_render(filename):
74 return markup.render(filename, code)
75
76 try:
77 lexer = get_lexer_for_filename(filename, code)
78 except ClassNotFound:
79 try:
80 lexer = guess_lexer(code)
81 except ClassNotFound:
82 lexer = TextLexer()
83 return highlight(code, lexer, KlausFormatter())
8448
8549
8650 def timesince(when, now=time.time):
154118
155119
156120 def shorten_sha1(sha1):
157 if re.match('[a-z\d]{20,40}', sha1):
121 if re.match(r'[a-z\d]{20,40}', sha1):
158122 sha1 = sha1[:7]
159123 return sha1
160124
00 import os
11
2 from flask import request, render_template, current_app
2 from flask import request, render_template, current_app, url_for
33 from flask.views import View
44
55 from werkzeug.wrappers import Response
88 from dulwich.objects import Blob
99
1010 from klaus import markup, tarutils
11 from klaus.utils import parent_directory, subpaths, pygmentize, encode_for_git, \
12 force_unicode, guess_is_binary, guess_is_image, replace_dupes
11 from klaus.highlighting import pygmentize
12 from klaus.utils import parent_directory, subpaths, force_unicode, guess_is_binary, \
13 guess_is_image, replace_dupes
1314
1415
1516 def repo_list():
2021 else:
2122 sort_key = lambda repo: repo.name
2223 reverse = False
23 repos = sorted(current_app.repos, key=sort_key, reverse=reverse)
24 repos = sorted(current_app.repos.values(), key=sort_key, reverse=reverse)
2425 return render_template('repo_list.html', repos=repos)
2526
2627
5455
5556 def make_template_context(self, repo, rev, path):
5657 try:
57 repo = current_app.repo_map[repo]
58 repo = current_app.repos[repo]
5859 except KeyError:
5960 raise NotFound("No such repository %r" % repo)
6061
174175
175176 class BaseFileView(TreeViewMixin, BaseBlobView):
176177 """Base for FileView and BlameView."""
178 def render_code(self, render_markup):
179 return pygmentize(
180 force_unicode(self.context['blob_or_tree'].data),
181 self.context['filename'],
182 render_markup,
183 )
184
177185 def make_template_context(self, *args):
178186 super(BaseFileView, self).make_template_context(*args)
179187 self.context.update({
206214 super(FileView, self).make_template_context(*args)
207215 if self.context['can_render']:
208216 render_markup = 'markup' not in request.args
209 rendered_code = pygmentize(
210 force_unicode(self.context['blob_or_tree'].data),
211 self.context['filename'],
212 render_markup
213 )
214217 self.context.update({
215218 'is_markup': markup.can_render(self.context['filename']),
216219 'render_markup': render_markup,
217 'rendered_code': rendered_code,
220 'rendered_code': self.render_code(render_markup),
218221 })
219222
220223
224227 def make_template_context(self, *args):
225228 super(BlameView, self).make_template_context(*args)
226229 if self.context['can_render']:
227 rendered_code = pygmentize(
228 force_unicode(self.context['blob_or_tree'].data),
229 self.context['filename'],
230 render_markup=False,
231 )
232230 line_commits = self.context['repo'].blame(self.context['commit'], self.context['path'])
233231 replace_dupes(line_commits, None)
234232 self.context.update({
235 'rendered_code': rendered_code,
233 'rendered_code': self.render_code(render_markup=False),
236234 'line_commits': line_commits,
237235 })
238236