DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (2d7b281bdf5d)

VCS Links

Line Code
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 99 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
#!/usr/bin/env python

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

"""
List mozbase package dependencies or generate changelogs
from commit messages.
"""

from __future__ import absolute_import, print_function

from collections import Iterable
from distutils.version import StrictVersion
import argparse
import os
import subprocess
import sys

import setup_development

here = os.path.abspath(os.path.dirname(__file__))


def run_hg(command):
    command = command[:]
    if not isinstance(command, Iterable):
        command = command.split()
    command.insert(0, 'hg')
    try:
        output = subprocess.check_output(command, cwd=here)
    except subprocess.CalledProcessError:
        sys.exit(1)
    return output


def changelog(args):
    setup = os.path.join(args.module, 'setup.py')

    def get_version_rev(v=None):
        revisions = run_hg(['log', setup, '--template={rev},']).split(',')[:-1]
        for rev in revisions:
            diff = run_hg(['diff', '-c', rev, setup, '-U0'])
            minus_version = None
            plus_version = None
            for line in diff.splitlines():
                if line.startswith('-PACKAGE_VERSION'):
                    try:
                        minus_version = StrictVersion(line.split()[-1].strip('"\''))
                    except ValueError:
                        pass
                elif line.startswith('+PACKAGE_VERSION'):
                    try:
                        plus_version = StrictVersion(line.split()[-1].strip('"\''))
                    except ValueError:
                        break

                    # make sure the change isn't a backout
                    if not minus_version or plus_version > minus_version:
                        if not v:
                            return rev

                        if StrictVersion(v) == plus_version:
                            return rev

        print("Could not find %s revision for version %s." % (args.module, v or 'latest'))
        sys.exit(1)

    from_ref = args.from_ref or get_version_rev()
    to_ref = args.to_ref or 'tip'

    if '.' in from_ref:
        from_ref = get_version_rev(from_ref)
    if '.' in to_ref:
        to_ref = get_version_rev(to_ref)

    delim = '\x12\x59\x52\x99\x05'
    changelog = run_hg(['log', '-r', '%s:children(%s)' % (to_ref, from_ref),
                        '--template={desc}%s' % delim,
                        '-M', args.module]).split(delim)[:-1]

    def prettify(desc):
        lines = desc.splitlines()
        lines = [('* %s' if i == 0 else '  %s') % l for i, l in enumerate(lines)]
        return '\n'.join(lines)

    changelog = map(prettify, changelog)
    print('\n'.join(changelog))


def dependencies(args):
    # get package information
    info = {}
    dependencies = {}
    for package in setup_development.mozbase_packages:
        directory = os.path.join(setup_development.here, package)
        info[directory] = setup_development.info(directory)
        name, _dependencies = setup_development.get_dependencies(directory)
        assert name == info[directory]['Name']
        dependencies[name] = _dependencies

    # print package version information
    for value in info.values():
        print('%s %s : %s' % (value['Name'], value['Version'],
                              ', '.join(dependencies[value['Name']])))


def main(args=sys.argv[1:]):
    parser = argparse.ArgumentParser()
    subcommands = parser.add_subparsers(help="Sub-commands")

    p_deps = subcommands.add_parser('dependencies', help="Print dependencies.")
    p_deps.set_defaults(func=dependencies)

    p_changelog = subcommands.add_parser('changelog', help="Print a changelog.")
    p_changelog.add_argument('module', help="Module to get changelog from.")
    p_changelog.add_argument('--from', dest='from_ref', default=None,
                             help="Starting version or revision to list "
                             "changes from. [defaults to latest version]")
    p_changelog.add_argument('--to', dest='to_ref', default=None,
                             help="Ending version or revision to list "
                             "changes to. [defaults to tip]")
    p_changelog.set_defaults(func=changelog)

    # default to showing dependencies
    if args == []:
        args.append('dependencies')
    args = parser.parse_args(args)
    args.func(args)


if __name__ == '__main__':
    main()