5 Commits
0.01 ... 0.10

Author SHA1 Message Date
Alberto Bertogli
36db9cc0ee Add a note about pygments in the README
Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>
2012-11-21 00:29:43 +00:00
Alberto Bertogli
bad8c52ef2 Fall back to guess the lexer by content
If we can't guess the lexer by the file name, try to guess based on the
content.

This allows pygments to colorize extension-less files, usually scripts.

Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>
2012-11-18 14:55:27 +00:00
Alberto Bertogli
62da3ebc08 Use heuristics to decide what to colorize
In practise pygments seems to have a very hard time processing large files and
files with long lines, so try to avoid using it in those cases.

Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>
2012-11-18 14:55:22 +00:00
Alberto Bertogli
ba3b2132f5 Improve the way we find repo paths
This patch improves the way we find the path to the repositories, both in the
recursive and in the non-recursive cases.

We now support specifying non-bare repositories directly, and also recursing
on them.

Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>
2012-11-11 13:43:02 +00:00
Alberto Bertogli
1c729578b2 Add dependencies and improve contact information to README
Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>
2012-11-11 12:53:39 +00:00
6 changed files with 85 additions and 22 deletions

15
README
View File

@@ -19,6 +19,13 @@ information.
Getting started
---------------
You will need Python, and the bottle.py framework (the package is usually
called python-bottle in most distributions).
If pygments is available, it will be used for syntax highlighting, otherwise
everything will work fine, just in black and white.
First, create a configuration file for your repositories. You can start by
copying sample.conf, which has the list of the available options.
@@ -41,9 +48,9 @@ use, by running:
That can be useful when making changes to the software itself.
Where to report bugs
--------------------
Contact
-------
If you want to report bugs, or have any questions or comments, just let me
know at albertito@blitiri.com.ar.
If you want to report bugs, send patches, or have any questions or comments,
just let me know at albertito@blitiri.com.ar.

44
git-arr
View File

@@ -49,14 +49,10 @@ def load_config(path):
# Do a first pass for general sanity checking and recursive expansion.
for s in config.sections():
if not config.has_option(s, 'path'):
raise configparser.NoOptionError(
'%s is missing the mandatory path' % s)
if config.getboolean(s, 'recursive'):
for path in os.listdir(config.get(s, 'path')):
fullpath = config.get(s, 'path') + '/' + path
if not os.path.exists(fullpath + '/HEAD'):
fullpath = find_git_dir(config.get(s, 'path') + '/' + path)
if not fullpath:
continue
if os.path.exists(fullpath + '/disable_gitweb'):
@@ -76,7 +72,13 @@ def load_config(path):
config.remove_section(s)
for s in config.sections():
fullpath = config.get(s, 'path')
fullpath = find_git_dir(config.get(s, 'path'))
if not fullpath:
raise ValueError(
'%s: path %s is not a valid git repository' % (
s, config.get(s, 'path')))
config.set(s, 'path', fullpath)
config.set(s, 'name', s)
desc = config.get(s, 'desc')
@@ -102,6 +104,29 @@ def load_config(path):
repos[r.name] = r
def find_git_dir(path):
"""Returns the path to the git directory for the given repository.
This function takes a path to a git repository, and returns the path to
its git directory. If the repo is bare, it will be the same path;
otherwise it will be path + '.git/'.
An empty string is returned if the given path is not a valid repository.
"""
def check(p):
"""A dirty check for whether this is a git dir or not."""
# Note silent stderr because we expect this to fail and don't want the
# noise; and also we strip the final \n from the output.
return git.run_git(p,
['rev-parse', '--git-dir'],
silent_stderr = True).read()[:-1]
for p in [ path, path + '/.git' ]:
if check(p):
return p
return ''
def repo_filter(unused_conf):
"""Bottle route filter for repos."""
@@ -133,7 +158,7 @@ def with_utils(f):
"""
utilities = {
'shorten': utils.shorten,
'has_colorizer': utils.has_colorizer,
'can_colorize': utils.can_colorize,
'colorize_diff': utils.colorize_diff,
'colorize_blob': utils.colorize_blob,
'abort': bottle.abort,
@@ -367,8 +392,9 @@ def main():
try:
load_config(opts.config)
except configparser.NoOptionError as e:
except (configparser.NoOptionError, ValueError) as e:
print('Error parsing config:', e)
return
if not args:
parser.error('Must specify an action (serve|generate)')

12
git.py
View File

@@ -41,7 +41,7 @@ class EncodeWrapper:
return s.decode(self.encoding, errors = self.errors)
def run_git(repo_path, params, stdin = None):
def run_git(repo_path, params, stdin = None, silent_stderr = False):
"""Invokes git with the given parameters.
This function invokes git with the given parameters, and returns a
@@ -49,11 +49,17 @@ def run_git(repo_path, params, stdin = None):
"""
params = [GIT_BIN, '--git-dir=%s' % repo_path] + list(params)
stderr = None
if silent_stderr:
stderr = subprocess.PIPE
if not stdin:
p = subprocess.Popen(params, stdin = None, stdout = subprocess.PIPE)
p = subprocess.Popen(params,
stdin = None, stdout = subprocess.PIPE, stderr = stderr)
else:
p = subprocess.Popen(params,
stdin = subprocess.PIPE, stdout = subprocess.PIPE)
stdin = subprocess.PIPE, stdout = subprocess.PIPE,
stderr = stderr)
p.stdin.write(stdin)
p.stdin.close()

View File

@@ -18,8 +18,28 @@ def shorten(s, width = 60):
return s
return s[:57] + "..."
def has_colorizer():
return pygments is not None
def can_colorize(s):
"""True if we can colorize the string, False otherwise."""
if pygments is None:
return False
# Pygments can take a huge amount of time with long files, or with very
# long lines; these are heuristics to try to avoid those situations.
if len(s) > (512 * 1024):
return False
# If any of the first 5 lines is over 300 characters long, don't colorize.
start = 0
for i in range(5):
pos = s.find('\n', start)
if pos == -1:
break
if pos - start > 300:
return False
start = pos + 1
return True
def colorize_diff(s):
lexer = lexers.DiffLexer(encoding = 'utf-8')
@@ -30,9 +50,13 @@ def colorize_diff(s):
def colorize_blob(fname, s):
try:
lexer = lexers.guess_lexer_for_filename(fname, s)
lexer = lexers.guess_lexer_for_filename(fname, s, encoding = 'utf-8')
except lexers.ClassNotFound:
lexer = lexers.TextLexer(encoding = 'utf-8')
try:
lexer = lexers.guess_lexer(s[:200], encoding = 'utf-8')
except lexers.ClassNotFound:
lexer = lexers.TextLexer(encoding = 'utf-8')
formatter = HtmlFormatter(encoding = 'utf-8',
cssclass = 'source_code',
linenos = 'table')

View File

@@ -36,7 +36,7 @@
<a href="">{{!fname.html}}</a>
</h3>
% if has_colorizer():
% if can_colorize(blob):
{{!colorize_blob(fname.unicode, blob)}}
% else:
<pre class="blob-body">

View File

@@ -55,7 +55,7 @@
<hr/>
% if has_colorizer():
% if can_colorize(c.diff.body):
{{!colorize_diff(c.diff.body)}}
% else:
<pre class="diff-body">