/* * Copyright 2015-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.cli; import com.facebook.buck.config.CellConfig; import com.facebook.buck.event.BuckEventListener; import com.facebook.buck.log.LogConfigSetup; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import java.io.IOException; import java.io.PrintStream; import java.util.Optional; import java.util.OptionalInt; import org.kohsuke.args4j.Option; import org.kohsuke.args4j.spi.SubCommand; import org.kohsuke.args4j.spi.SubCommands; public abstract class AbstractContainerCommand implements Command { @Option( name = "--help", aliases = {"-h"}, usage = "Shows this screen and exits." ) @SuppressWarnings("PMD.UnusedPrivateField") private boolean helpScreen; protected String getSubcommandsFieldName() { return "subcommand"; } protected abstract Optional<Command> getSubcommand(); protected abstract String getContainerCommandPrefix(); @Override public OptionalInt runHelp(PrintStream stream) { if (getSubcommand().isPresent()) { return getSubcommand().get().runHelp(stream); } else if (helpScreen) { printUsage(stream); return OptionalInt.of(1); } else { return OptionalInt.empty(); } } @Override public int run(CommandRunnerParams params) throws IOException, InterruptedException { Optional<Command> subcommand = getSubcommand(); if (subcommand.isPresent()) { return subcommand.get().run(params); } else { printUsage(params.getConsole().getStdErr()); return 1; } } @Override public void printUsage(PrintStream stream) { String prefix = getContainerCommandPrefix(); stream.println("buck build tool"); stream.println("Usage:"); stream.println(" " + prefix + " [<options>]"); stream.println(" " + prefix + " <command> --help"); stream.println(" " + prefix + " <command> [<command-options>]"); stream.println(); stream.println("Available commands:"); SubCommands subCommands; try { subCommands = this.getClass() .getDeclaredField(getSubcommandsFieldName()) .getAnnotation(SubCommands.class); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } int lengthOfLongestCommand = 0; for (SubCommand subCommand : subCommands.value()) { String name = subCommand.name(); if (name.length() > lengthOfLongestCommand) { lengthOfLongestCommand = name.length(); } } for (SubCommand subCommand : subCommands.value()) { Command command; try { command = (Command) subCommand.impl().newInstance(); } catch (IllegalAccessException | InstantiationException e) { throw new RuntimeException(e); } String name = subCommand.name().toLowerCase(); stream.printf( " %s%s %s\n", name, Strings.repeat(" ", lengthOfLongestCommand - name.length()), command.getShortDescription()); } stream.println(); stream.println("Options:"); new AdditionalOptionsCmdLineParser(this).printUsage(stream); stream.println(); } @Override public CellConfig getConfigOverrides() { Optional<Command> cmd = getSubcommand(); return cmd.isPresent() ? cmd.get().getConfigOverrides() : CellConfig.of(); } @Override public LogConfigSetup getLogConfig() { Optional<Command> cmd = getSubcommand(); return cmd.isPresent() ? cmd.get().getLogConfig() : LogConfigSetup.DEFAULT_SETUP; } @Override public boolean isSourceControlStatsGatheringEnabled() { return false; } @Override public Iterable<BuckEventListener> getEventListeners() { if (!getSubcommand().isPresent()) { return ImmutableList.of(); } return getSubcommand().get().getEventListeners(); } }