/*
* 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.parser.BuildTargetPatternTargetNodeParser;
import com.facebook.buck.parser.TargetNodeSpec;
import com.facebook.buck.rules.CellPathResolver;
import com.facebook.buck.util.MoreStrings;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
import java.util.Optional;
public class CommandLineTargetNodeSpecParser {
private final BuckConfig config;
private final BuildTargetPatternTargetNodeParser parser;
public CommandLineTargetNodeSpecParser(
BuckConfig config, BuildTargetPatternTargetNodeParser parser) {
this.config = config;
this.parser = parser;
}
@VisibleForTesting
protected String normalizeBuildTargetString(String target) {
// Check and save the cell name
int targetSeparator = target.indexOf("//");
String cellName = "";
if (targetSeparator > 0) {
cellName = target.substring(0, targetSeparator);
target = target.substring(targetSeparator);
}
// Strip out the leading "//" if there is one to make it easier to normalize the
// remaining target string. We'll add this back at the end.
target = MoreStrings.stripPrefix(target, "//").orElse(target);
// Look up the section after the colon, if present, and strip it off.
int colonIndex = target.indexOf(':');
Optional<String> nameAfterColon = Optional.empty();
if (colonIndex != -1) {
nameAfterColon = Optional.of(target.substring(colonIndex + 1, target.length()));
target = target.substring(0, colonIndex);
}
// Strip trailing slashes in the directory name part.
while (target.endsWith("/")) {
target = target.substring(0, target.length() - 1);
}
// If no colon was specified and we're not dealing with a trailing "...", we'll add in the
// missing colon and fill in the missing rule name with the basename of the directory.
if (!nameAfterColon.isPresent() && !target.endsWith("/...") && !target.equals("...")) {
int lastSlashIndex = target.lastIndexOf('/');
if (lastSlashIndex == -1) {
nameAfterColon = Optional.of(target);
} else {
nameAfterColon = Optional.of(target.substring(lastSlashIndex + 1));
}
}
// Now add in the name after the colon if there was one.
if (nameAfterColon.isPresent()) {
target += ":" + nameAfterColon.get();
}
return cellName + "//" + target;
}
public ImmutableSet<TargetNodeSpec> parse(CellPathResolver cellNames, String arg) {
ImmutableSet<String> resolvedArgs = config.getBuildTargetForAliasAsString(arg);
if (resolvedArgs.isEmpty()) {
resolvedArgs = ImmutableSet.of(arg);
}
ImmutableSet.Builder<TargetNodeSpec> specs = new ImmutableSet.Builder<>();
for (String resolvedArg : resolvedArgs) {
String buildTarget = normalizeBuildTargetString(resolvedArg);
specs.add(parser.parse(cellNames, buildTarget));
}
return specs.build();
}
}