blob: 65488aefcfdc7de0421994ba40a438c5c1e96c70 [file] [log] [blame]
/*
* Copyright 2012-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.model;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import java.io.File;
import javax.annotation.Nullable;
public final class BuildTarget implements Comparable<BuildTarget> {
@VisibleForTesting
public static final String BUILD_TARGET_PREFIX = "//";
private final File buildFile;
private final String baseName;
private final String shortName;
/**
* Reserved for special internal targets such as {@link BuildTarget#ANDROID_SDK}, as well as
* fake targets for testing.
*/
@VisibleForTesting
BuildTarget(String baseName, String shortName) {
this(baseName, shortName, null /* buildFile */);
}
/**
* Reserved for testing: normal constructor precondition checks are omitted.
*/
@VisibleForTesting
BuildTarget(String baseName, String shortName, File buildFile) {
this.buildFile = buildFile;
this.baseName = Preconditions.checkNotNull(baseName);
this.shortName = Preconditions.checkNotNull(shortName);
}
public BuildTarget(File buildFile, String baseName, String shortName) {
Preconditions.checkNotNull(buildFile);
Preconditions.checkArgument(buildFile.isFile(), "%s must be a file", buildFile);
this.buildFile = buildFile;
Preconditions.checkNotNull(baseName);
Preconditions.checkArgument(baseName.startsWith(BUILD_TARGET_PREFIX),
"baseName must start with // but was %s",
baseName);
String parentDirectoryName = buildFile.getParentFile().getAbsolutePath();
String basePath = baseName.substring(BUILD_TARGET_PREFIX.length());
Preconditions.checkArgument(parentDirectoryName.endsWith(basePath),
"file path %s did not end with %s for %s:%s", parentDirectoryName, basePath, baseName, shortName);
this.baseName = baseName;
this.shortName = Preconditions.checkNotNull(shortName);
}
/**
* For use by InputRule, which is synthetic, and therefore has no buildFile.
* @param inputFile Input file.
* @param relativePath
*/
private BuildTarget(File inputFile, String relativePath) {
Preconditions.checkNotNull(inputFile);
Preconditions.checkNotNull(relativePath);
this.buildFile = null;
this.baseName = String.format("//%s", relativePath);
this.shortName = inputFile.getName();
}
/**
* For exclusive use by {@link com.facebook.buck.rules.InputRule#InputRule(File, String)}.
*/
public static BuildTarget createBuildTargetForInputFile(File inputFile, String relativePath) {
return new BuildTarget(inputFile, relativePath);
}
/**
* The build file in which this rule was defined.
*/
@Nullable
public File getBuildFile() {
return buildFile;
}
/**
* The directory that contains the corresponding build file.
*/
public File getBuildFileDirectory() {
return buildFile.getParentFile();
}
/**
* If this build target were //third_party/java/guava:guava-latest, then this would return
* "guava-latest".
*/
public String getShortName() {
return shortName;
}
/**
* If this build target were //third_party/java/guava:guava-latest, then this would return
* "//third_party/java/guava".
*/
public String getBaseName() {
return baseName;
}
/**
* If this build target were //third_party/java/guava:guava-latest, then this would return
* "//third_party/java/guava/".
*/
public String getBaseNameWithSlash() {
return getBaseNameWithSlash(baseName);
}
/**
* Helper function for getting BuildTarget base names with a trailing slash if needed.
*
* If baseName were //third_party/java/guava, then this would return "//third_party/java/guava/".
* If it were //, it would return //.
*/
@Nullable
public static String getBaseNameWithSlash(@Nullable String baseName) {
return baseName == null || baseName.equals(BUILD_TARGET_PREFIX) ? baseName : baseName + "/";
}
/**
* If this build target were //third_party/java/guava:guava-latest, then this would return
* "third_party/java/guava". This does not contain the "//" prefix so that it can be appended to
* a file path.
*/
public String getBasePath() {
return baseName.substring(BUILD_TARGET_PREFIX.length());
}
/**
* @return the value of {@link #getBasePath()} with a trailing slash, unless
* {@link #getBasePath()} returns the empty string, in which case this also returns the empty
* string
*/
public String getBasePathWithSlash() {
String basePath = getBasePath();
return basePath.isEmpty() ? "" : basePath + "/";
}
/**
* If this build target is //third_party/java/guava:guava-latest, then this would return
* "//third_party/java/guava:guava-latest".
*/
public String getFullyQualifiedName() {
return String.format("%s:%s", baseName, shortName);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof BuildTarget)) {
return false;
}
BuildTarget that = (BuildTarget)o;
return Objects.equal(this.buildFile, that.buildFile)
&& Objects.equal(this.baseName, that.baseName)
&& Objects.equal(this.shortName, that.shortName);
}
@Override
public int hashCode() {
return Objects.hashCode(buildFile, baseName, shortName);
}
/** @return {@link #getFullyQualifiedName()} */
@Override
public String toString() {
return getFullyQualifiedName();
}
@Override
public int compareTo(BuildTarget target) {
Preconditions.checkNotNull(target);
return getFullyQualifiedName().compareTo(target.getFullyQualifiedName());
}
}