common.py
78 lines
| 2.7 KiB
| text/x-python
|
PythonLexer
Eric Hopper
|
r2391 | # hgweb/common.py - Utility functions needed by hgweb_mod and hgwebdir_mod | ||
Eric Hopper
|
r2356 | # | ||
# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net> | ||||
Vadim Gelfer
|
r2859 | # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com> | ||
Eric Hopper
|
r2356 | # | ||
# This software may be used and distributed according to the terms | ||||
# of the GNU General Public License, incorporated herein by reference. | ||||
import os, mimetypes | ||||
def get_mtime(repo_path): | ||||
Benoit Boissinot
|
r3853 | store_path = os.path.join(repo_path, ".hg") | ||
if not os.path.isdir(os.path.join(store_path, "data")): | ||||
store_path = os.path.join(store_path, "store") | ||||
cl_path = os.path.join(store_path, "00changelog.i") | ||||
if os.path.exists(cl_path): | ||||
Eric Hopper
|
r2356 | return os.stat(cl_path).st_mtime | ||
else: | ||||
Benoit Boissinot
|
r3853 | return os.stat(store_path).st_mtime | ||
Eric Hopper
|
r2356 | |||
Eric Hopper
|
r2514 | def staticfile(directory, fname, req): | ||
Eric Hopper
|
r2356 | """return a file inside directory with guessed content-type header | ||
fname always uses '/' as directory separator and isn't allowed to | ||||
contain unusual path components. | ||||
Content-type is guessed using the mimetypes module. | ||||
Return an empty string if fname is illegal or file not found. | ||||
""" | ||||
parts = fname.split('/') | ||||
path = directory | ||||
for part in parts: | ||||
if (part in ('', os.curdir, os.pardir) or | ||||
os.sep in part or os.altsep is not None and os.altsep in part): | ||||
return "" | ||||
path = os.path.join(path, part) | ||||
try: | ||||
os.stat(path) | ||||
ct = mimetypes.guess_type(path)[0] or "text/plain" | ||||
Eric Hopper
|
r2514 | req.header([('Content-type', ct), | ||
Alexis S. L. Carvalho
|
r4038 | ('Content-length', str(os.path.getsize(path)))]) | ||
Wojciech Milkowski
|
r3244 | return file(path, 'rb').read() | ||
Eric Hopper
|
r2356 | except (TypeError, OSError): | ||
# illegal fname or unreadable file | ||||
return "" | ||||
Thomas Arendsen Hein
|
r3276 | |||
def style_map(templatepath, style): | ||||
"""Return path to mapfile for a given style. | ||||
Searches mapfile in the following locations: | ||||
1. templatepath/style/map | ||||
2. templatepath/map-style | ||||
3. templatepath/map | ||||
""" | ||||
locations = style and [os.path.join(style, "map"), "map-"+style] or [] | ||||
locations.append("map") | ||||
for location in locations: | ||||
mapfile = os.path.join(templatepath, location) | ||||
if os.path.isfile(mapfile): | ||||
return mapfile | ||||
raise RuntimeError("No hgweb templates found in %r" % templatepath) | ||||
Thomas Arendsen Hein
|
r4462 | def paritygen(stripecount, offset=0): | ||
"""count parity of horizontal stripes for easier reading""" | ||||
if stripecount and offset: | ||||
# account for offset, e.g. due to building the list in reverse | ||||
count = (stripecount + offset) % stripecount | ||||
parity = (stripecount + offset) / stripecount & 1 | ||||
else: | ||||
count = 0 | ||||
parity = 0 | ||||
while True: | ||||
yield parity | ||||
count += 1 | ||||
if stripecount and count >= stripecount: | ||||
parity = 1 - parity | ||||
count = 0 | ||||