#!/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.abc import Iterable from distutils.version import StrictVersion import argparse import os import subprocess import sys here = os.path.abspath(os.path.dirname(__file__)) sys.path.insert(0, here) import setup_development 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, universal_newlines=True) 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()