aboutsummaryrefslogtreecommitdiff
path: root/git-repo-url-rewrite/git-directory-rewritemap.py
blob: 586ee4887770a642e2d56a4069f7ba8322693d2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/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