version.py 4.21 KB
Newer Older
John Jarvis committed
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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
#!/usr/bin/env python
import os
import subprocess
import re
import json
import glob

ROOT_DIR = '/opt/wwc'
VERSION_FILE = '/opt/wwc/versions.html'
VERSION_JSON = '/opt/wwc/versions.json'
GLOB_DIRS = [
              os.path.join(ROOT_DIR, '*/.git'),
              os.path.join(ROOT_DIR, '*/*/.git'),
              os.path.join(ROOT_DIR, 'data/*/.git'),
            ]


TEMPLATE = """
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>

    <style>
      body {{
         font-size: 2em;
         color: #000;
         font-family: monospace;
      }}
    </style>

  </head>
<body>
<ul>
  {BODY}
</ul>
</body>
<script type="text/javascript">
  $(".collapse").click(function () {{
        $(this).parent().children().toggle();
        $(this).toggle();

        }});
  $(document).ready(function() {{
        $('.collapse').parent().children().toggle();
        $('.collapse').toggle();
  }});
</script>
</html>
"""


def main():
    assert os.path.isdir(ROOT_DIR)
    # using glob with fixed depths is much
    # faster than os.walk for finding all .git repos
    git_dirs = [git_dir for glob_dir in GLOB_DIRS
                for git_dir in glob.glob(glob_dir)]
    git_dirs = filter(lambda f: os.path.isdir(f), git_dirs)

    version_info = ""
    versions = {}

    for git_dir in git_dirs:
        repo_dir = git_dir.replace('/.git', '')
        repo_dir_basename = os.path.basename(repo_dir)

        # get the revision of the repo
        p = subprocess.Popen(['/usr/bin/git', 'rev-parse', 'HEAD'],
                    stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                    cwd=git_dir)
        rev_output, rev_err = p.communicate()
        revision = rev_output.splitlines()[0][:8]

        # dictionary that will be written out as JSON
        versions[repo_dir_basename] = revision

        # use reflogs for the repo history
        p = subprocess.Popen(
          ['/usr/bin/git', 'log', '-g', '--abbrev-commit', '--pretty=oneline'],
           stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=git_dir)

        reflog_output, reflog_err = p.communicate()

        # ignore lines that do not have 'HEAD'
        reflog_lines = filter(lambda x: x.find('HEAD') >= 0,
                                            reflog_output.splitlines())

        # get the repo name, `git remote -v` seems like the fastest option
        p = subprocess.Popen(['/usr/bin/git', 'remote', '-v'],
                    stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                    cwd=git_dir)
        remote_output, remote_err = p.communicate()
        repo_url = None
        for line in remote_output.splitlines():
            if ' (fetch)' in line:
                repo_url = re.search(
99
                        '(git@|git://)(.*) \(fetch\)', line).group(2).replace(
John Jarvis committed
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
                                                                ':', '/')
                break
        if not repo_url:
            raise Exception("Unable to parse repo name")

        version_info += """
          <li> <span class="collapse"> <a href="http://{0}">{1}</a> - {2}
                [ click for history (most recent last) ]</span>
          <ul>""".format(repo_url, repo_dir_basename, revision)

        ref_prev = None
        for line in reflog_lines[:0:-1]:
            ref = line.split()[0]
            version_info += """
              <li><span class="collapse">{ref} -
              <a href="http://{repo}/compare/{ref}...{revision}">[diff current]</a>
              """.format(ref=ref, repo=repo_url, revision=revision)

            if ref_prev:
                version_info += """
                <a href="http://{repo}/compare/{ref_prev}...{ref}">[diff previous]</a>
                """.format(repo=repo_url, ref=ref, ref_prev=ref_prev)
            version_info += "</span></li>"
            ref_prev = ref
        version_info += """
          </ul></li>"""

    with open(VERSION_FILE, 'w') as f:
        f.write(TEMPLATE.format(BODY=version_info))
    with open(VERSION_JSON, 'w') as f:
        f.write(json.dumps(versions, sort_keys=True, indent=4,
                        separators=(',', ': ')))

if __name__ == '__main__':
    main()