summaryrefslogtreecommitdiffstats
path: root/testing/mozbase/versioninfo.py
blob: 0aaff23ad08ebce78278c0f7e8c242a3d87685c9 (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
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/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)

    # pylint --py3k: W1636
    changelog = list(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()