def execute(self, targets): goal = self.context.options.help_goal if goal is None: return self.list_goals('You must supply a goal name to provide help for.') phase = Phase(goal) if not phase.goals(): return self.list_goals('Goal %s is unknown.' % goal) parser = Help.parser() parser.set_usage('%s goal %s ([target]...)' % (sys.argv[0], goal)) parser.epilog = phase.description Phase.setup_parser(parser, [], [phase]) parser.parse_args(['--help'])
def setup_parser(self, parser, args): self.config = Config.load() parser.add_option("-x", "--time", action="store_true", dest = "time", default = False, help = "Times goal phases and outputs a report.") parser.add_option("-v", "--log", action="store_true", dest = "log", default = False, help = "[%default] Logs extra build output.") parser.add_option("-l", "--level", dest = "log_level", type="choice", choices=['debug', 'info', 'warn'], help = "[info] Sets the logging level to one of 'debug', 'info' or 'warn', " "implies -v if set.") parser.add_option("--all", dest="target_directory", action="append", help = "Adds all targets found in the given directory's BUILD file. Can " "be specified more than once.") parser.add_option("--all-recursive", dest="recursive_directory", action="append", help = "Adds all targets found recursively under the given directory. Can " "be specified more than once to add more than one root target " "directory to scan.") # We support attempting zero or more goals. Multiple goals must be delimited from further # options and non goal args with a '--'. The key permutations we need to support: # ./pants goal => goals # ./pants goal goals => goals # ./pants goal compile src/java/... => compile # ./pants goal compile -x src/java/... => compile # ./pants goal compile src/java/... -x => compile # ./pants goal compile run -- src/java/... => compile, run # ./pants goal compile run -- src/java/... -x => compile, run # ./pants goal compile run -- -x src/java/... => compile, run if not args: args.append('goals') if len(args) == 1 and args[0] in set(['-h', '--help', 'help']): def format_usage(usages): left_colwidth = 0 for left, right in usages: left_colwidth = max(left_colwidth, len(left)) lines = [] for left, right in usages: lines.append(' %s%s%s' % (left, ' ' * (left_colwidth - len(left) + 1), right)) return '\n'.join(lines) usages = [ ("%prog goal goals ([spec]...)", Phase('goals').description), ("%prog goal help [goal] ([spec]...)", Phase('help').description), ("%prog goal [goal] [spec]...", "Attempt goal against one or more targets."), ("%prog goal [goal] ([goal]...) -- [spec]...", "Attempts all the specified goals."), ] parser.set_usage("\n%s" % format_usage(usages)) parser.epilog = ("Either lists all installed goals, provides extra help for a goal or else " "attempts to achieve the specified goal for the listed targets.") parser.print_help() sys.exit(0) else: goals = [] help = False multi = False for i, arg in enumerate(args): help = help or 'help' == arg goals.append(arg) if '--' == arg: multi = True del args[i] goals.pop() break if arg.startswith('-'): break if not multi: goals = [goals[0]] spec_offset = len(goals) + 1 if help else len(goals) specs = [arg for arg in args[spec_offset:] if not arg.startswith('-')] def parse_build(buildfile): # TODO(John Sirois): kill PANTS_NEW and its usages when pants.new is rolled out ParseContext(buildfile).parse(PANTS_NEW=True) # Bootstrap goals by loading any configured bootstrap BUILD files with self.check_errors('The following bootstrap_buildfiles cannot be loaded:') as error: for path in self.config.getlist('goals', 'bootstrap_buildfiles', default = []): try: buildfile = BuildFile(get_buildroot(), os.path.relpath(path, get_buildroot())) parse_build(buildfile) except (TypeError, ImportError): error(path, include_traceback=True) except (IOError, SyntaxError): error(path) # Bootstrap user goals by loading any BUILD files implied by targets self.targets = [] with self.check_errors('The following targets could not be loaded:') as error: for spec in specs: try: address = Address.parse(get_buildroot(), spec) parse_build(address.buildfile) target = Target.get(address) if target: self.targets.append(target) else: siblings = Target.get_all_addresses(address.buildfile) prompt = 'did you mean' if len(siblings) == 1 else 'maybe you meant one of these' error('%s => %s?:\n %s' % (address, prompt, '\n '.join(str(a) for a in siblings))) except (TypeError, ImportError): error(spec, include_traceback=True) except (IOError, SyntaxError): error(spec) self.phases = [Phase(goal) for goal in goals] Phase.setup_parser(parser, args, self.phases)