| // Copyright 2014 The Bazel Authors. All rights reserved. | 
 | // | 
 | // 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.google.devtools.build.lib.util; | 
 |  | 
 | import static com.google.common.base.Preconditions.checkNotNull; | 
 |  | 
 | import com.google.common.base.StandardSystemProperty; | 
 | import com.google.common.collect.ImmutableList; | 
 | import com.google.devtools.build.lib.vfs.PathFragment; | 
 | import com.google.devtools.common.options.Converter; | 
 | import com.google.devtools.common.options.OptionsParsingException; | 
 | import com.google.devtools.common.options.OptionsParsingResult; | 
 | import com.google.devtools.common.options.ParsedOptionDescription; | 
 | import java.util.List; | 
 |  | 
 | /** Blaze-specific option utilities. */ | 
 | public final class OptionsUtils { | 
 |  | 
 |   /** | 
 |    * Returns a string representation of the non-hidden specified options; option values are | 
 |    * shell-escaped. | 
 |    */ | 
 |   public static String asShellEscapedString(Iterable<ParsedOptionDescription> optionsList) { | 
 |     StringBuilder result = new StringBuilder(); | 
 |     for (ParsedOptionDescription option : optionsList) { | 
 |       if (option.isHidden()) { | 
 |         continue; | 
 |       } | 
 |       if (result.length() != 0) { | 
 |         result.append(' '); | 
 |       } | 
 |       result.append(option.getCanonicalFormWithValueEscaper(ShellEscaper::escapeString)); | 
 |     } | 
 |     return result.toString(); | 
 |   } | 
 |  | 
 |   /** | 
 |    * Returns a string representation of the non-hidden explicitly or implicitly specified options; | 
 |    * option values are shell-escaped. | 
 |    */ | 
 |   public static String asShellEscapedString(OptionsParsingResult options) { | 
 |     return asShellEscapedString(options.asCompleteListOfParsedOptions()); | 
 |   } | 
 |  | 
 |   /** | 
 |    * Return a representation of the non-hidden specified options, as a list of string. No escaping | 
 |    * is done. | 
 |    */ | 
 |   public static List<String> asArgumentList(Iterable<ParsedOptionDescription> optionsList) { | 
 |     ImmutableList.Builder<String> builder = ImmutableList.builder(); | 
 |     for (ParsedOptionDescription option : optionsList) { | 
 |       if (option.isHidden()) { | 
 |         continue; | 
 |       } | 
 |       builder.add(option.getCanonicalForm()); | 
 |     } | 
 |     return builder.build(); | 
 |   } | 
 |  | 
 |   /** | 
 |    * Return a representation of the non-hidden specified options, as a list of string. No escaping | 
 |    * is done. | 
 |    */ | 
 |   public static List<String> asArgumentList(OptionsParsingResult options) { | 
 |     return asArgumentList(options.asCompleteListOfParsedOptions()); | 
 |   } | 
 |  | 
 |   /** | 
 |    * Returns a string representation of the non-hidden explicitly or implicitly specified options, | 
 |    * filtering out any sensitive options; option values are shell-escaped. | 
 |    */ | 
 |   public static String asFilteredShellEscapedString( | 
 |       OptionsParsingResult options, Iterable<ParsedOptionDescription> optionsList) { | 
 |     return asShellEscapedString(optionsList); | 
 |   } | 
 |  | 
 |   /** | 
 |    * Returns a string representation of the non-hidden explicitly or implicitly specified options, | 
 |    * filtering out any sensitive options; option values are shell-escaped. | 
 |    */ | 
 |   public static String asFilteredShellEscapedString(OptionsParsingResult options) { | 
 |     return asFilteredShellEscapedString(options, options.asCompleteListOfParsedOptions()); | 
 |   } | 
 |  | 
 |   /** Converter from String to PathFragment. */ | 
 |   public static class PathFragmentConverter implements Converter<PathFragment> { | 
 |  | 
 |     @Override | 
 |     public PathFragment convert(String input) { | 
 |       return convertOptionsPathFragment(checkNotNull(input)); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public String getTypeDescription() { | 
 |       return "a path"; | 
 |     } | 
 |   } | 
 |  | 
 |   /** Converter from String to PathFragment requiring the provided path to be absolute. */ | 
 |   public static class AbsolutePathFragmentConverter implements Converter<PathFragment> { | 
 |  | 
 |     @Override | 
 |     public PathFragment convert(String input) throws OptionsParsingException { | 
 |       PathFragment parsed = convertOptionsPathFragment(checkNotNull(input)); | 
 |       if (!parsed.isAbsolute()) { | 
 |         throw new OptionsParsingException(String.format("Not an absolute path: '%s'", input)); | 
 |       } | 
 |       return parsed; | 
 |     } | 
 |  | 
 |     @Override | 
 |     public String getTypeDescription() { | 
 |       return "an absolute path"; | 
 |     } | 
 |   } | 
 |  | 
 |   /** Converter from String to PathFragment. If the input is empty returns {@code null} instead. */ | 
 |   public static class EmptyToNullRelativePathFragmentConverter implements Converter<PathFragment> { | 
 |  | 
 |     @Override | 
 |     public PathFragment convert(String input) throws OptionsParsingException { | 
 |       if (input.isEmpty()) { | 
 |         return null; | 
 |       } | 
 |  | 
 |       PathFragment pathFragment = convertOptionsPathFragment(input); | 
 |  | 
 |       if (pathFragment.isAbsolute()) { | 
 |         throw new OptionsParsingException("Expected relative path but got '" + input + "'."); | 
 |       } | 
 |  | 
 |       return pathFragment; | 
 |     } | 
 |  | 
 |     @Override | 
 |     public String getTypeDescription() { | 
 |       return "a relative path"; | 
 |     } | 
 |   } | 
 |  | 
 |   /** Converts from a colon-separated list of strings into a list of PathFragment instances. */ | 
 |   public static class PathFragmentListConverter implements Converter<ImmutableList<PathFragment>> { | 
 |  | 
 |     @Override | 
 |     public ImmutableList<PathFragment> convert(String input) { | 
 |       ImmutableList.Builder<PathFragment> result = ImmutableList.builder(); | 
 |       for (String piece : input.split(":")) { | 
 |         if (!piece.isEmpty()) { | 
 |           result.add(convertOptionsPathFragment(piece)); | 
 |         } | 
 |       } | 
 |       return result.build(); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public String getTypeDescription() { | 
 |       return "a colon-separated list of paths"; | 
 |     } | 
 |   } | 
 |  | 
 |   private static PathFragment convertOptionsPathFragment(String path) { | 
 |     if (!path.isEmpty() && path.startsWith("~/")) { | 
 |       path = path.replace("~", StandardSystemProperty.USER_HOME.value()); | 
 |     } | 
 |     return PathFragment.create(path); | 
 |   } | 
 | } |