#!/usr/bin/python -u # Copyright 2012 Linaro. """Allow accessing .git directories without '.git' in the name. To be used with Apache2 mod_rewrite RewriteMap functionality. This means that "-u" option to python interpreter above is important for unbuffered output. """ import os BASE_PATH = '/srv/repositories' def relativize_path(path): """Ensure `path` does not start with '/'.""" path = os.path.normpath(path) if path[0] == os.sep: path = path[1:] return path def rewrite_path(base_path, file_path): """Return a rewritten path with '.git' added where necessary. Looks for all the directories with '.git' appended that exist on disk in `base_path`/`file_path` right-to-left until it finds it. Returns None if `file_path` can not be matched, otherwise, returns a matched file path relative to `base_path`. """ file_path = relativize_path(file_path) full_path = os.path.join(base_path, file_path) dirname, current = os.path.split(full_path) filename = '' while current != '': git_dirname = os.path.join(dirname, current) git_dirname2 = git_dirname + '.git' # If git_dirname does not exist but a variant with '.git' # appended does, use the version with '.git' appended. if os.path.isdir(git_dirname2): if not os.path.isdir(git_dirname): git_dirname = git_dirname2 else: # In case both .git and .git-less dir exists, prefer .git if # we access files/dirs usually located within .git dir. for internal in ["info/", "objects/", "refs/", "branches/", "logs/"]: if filename.startswith(internal): git_dirname = git_dirname2 break # 'filename' is a string representing the right-hand side # of the path being looked at. if filename: file_path = os.path.join(git_dirname, filename) filename = os.path.join(current, filename) else: file_path = git_dirname filename = current if os.path.exists(file_path): return os.path.relpath(file_path, base_path) dirname, current = os.path.split(dirname) return None if __name__ == '__main__': while True: request_path = raw_input() desired_path = rewrite_path(BASE_PATH, request_path) if desired_path is None: print request_path else: if request_path.startswith(os.sep): print "/" + desired_path else: print desired_path