diff --git a/build/fbcode_builder/getdeps.py b/build/fbcode_builder/getdeps.py new file mode 100755 index 0000000000..144c7d000a --- /dev/null +++ b/build/fbcode_builder/getdeps.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# Copyright (c) 2019-present, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. An additional grant +# of patent rights can be found in the PATENTS file in the same directory. + + +from __future__ import absolute_import, division, print_function, unicode_literals + +import argparse +import os +import subprocess +import sys + +from getdeps.manifest import ManifestParser +from getdeps.subcmd import SubCmd, add_subcommands, cmd + + +sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "getdeps")) + + +@cmd("validate-manifest", "parse a manifest and validate that it is correct") +class ValidateManifest(SubCmd): + def run(self, args): + try: + ManifestParser(file_name=args.file_name) + print("OK", file=sys.stderr) + return 0 + except Exception as exc: + print("ERROR: %s" % str(exc), file=sys.stderr) + return 1 + + def setup_parser(self, parser): + parser.add_argument("file_name", help="path to the manifest file") + + +def build_argparser(): + ap = argparse.ArgumentParser(description="Get and build dependencies and projects") + sub = ap.add_subparsers( + # metavar suppresses the long and ugly default list of subcommands on a + # single line. We still render the nicer list below where we would + # have shown the nasty one. + metavar="", + title="Available commands", + help="", + ) + + add_subcommands(sub) + + return ap + + +def main(): + ap = build_argparser() + args = ap.parse_args() + if getattr(args, "func", None) is None: + ap.print_help() + return 0 + try: + return args.func(args) + except subprocess.CalledProcessError: + print("!! Failed", file=sys.stderr) + return 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/build/fbcode_builder/getdeps/__init__.py b/build/fbcode_builder/getdeps/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/build/fbcode_builder/getdeps/subcmd.py b/build/fbcode_builder/getdeps/subcmd.py new file mode 100644 index 0000000000..205e1d8b19 --- /dev/null +++ b/build/fbcode_builder/getdeps/subcmd.py @@ -0,0 +1,58 @@ +# Copyright (c) 2019-present, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. An additional grant +# of patent rights can be found in the PATENTS file in the same directory. + +from __future__ import absolute_import, division, print_function, unicode_literals + + +class SubCmd(object): + NAME = None + HELP = None + + def run(self, args): + """ perform the command """ + return 0 + + def setup_parser(self, parser): + # Subclasses should override setup_parser() if they have any + # command line options or arguments. + pass + + +CmdTable = [] + + +def add_subcommands(parser, cmd_table=CmdTable): + """ Register parsers for the defined commands with the provided parser """ + for cls in cmd_table: + command = cls() + command_parser = parser.add_parser(command.NAME, help=command.HELP) + command.setup_parser(command_parser) + command_parser.set_defaults(func=command.run) + + +def cmd(name, help=None, cmd_table=CmdTable): + """ + @cmd() is a decorator that can be used to help define Subcmd instances + + Example usage: + + @subcmd('list', 'Show the result list') + class ListCmd(Subcmd): + def run(self, args): + # Perform the command actions here... + pass + """ + + def wrapper(cls): + class SubclassedCmd(cls): + NAME = name + HELP = help + + cmd_table.append(SubclassedCmd) + return SubclassedCmd + + return wrapper