blob: 3527d1c4a4f854b2c652fdb37099bcada91d56db [file] [log] [blame]
// Copyright 2015 Google Inc. 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.workspace;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.bazel.BazelMain;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.TargetParsingException;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.packages.AggregatingAttributeMapper;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.ExternalPackage;
import com.google.devtools.build.lib.packages.RuleClassProvider;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.packages.WorkspaceFactory;
import com.google.devtools.build.lib.runtime.BlazeModule;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.syntax.ParserInputSource;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.workspace.maven.DefaultModelResolver;
import com.google.devtools.build.workspace.maven.Rule;
import org.apache.maven.model.building.ModelSource;
import org.apache.maven.model.resolution.UnresolvableModelException;
import java.io.IOException;
import java.util.List;
/**
* Finds the transitive dependencies of a WORKSPACE file.
*/
public class Resolver {
private final RuleClassProvider ruleClassProvider;
private final EventHandler handler;
private final com.google.devtools.build.workspace.maven.Resolver resolver;
Resolver(com.google.devtools.build.workspace.maven.Resolver resolver, EventHandler handler) {
this.resolver = resolver;
this.handler = handler;
ConfiguredRuleClassProvider.Builder ruleClassBuilder =
new ConfiguredRuleClassProvider.Builder();
List<BlazeModule> blazeModules = BlazeRuntime.createModules(BazelMain.BAZEL_MODULES);
for (BlazeModule blazeModule : blazeModules) {
blazeModule.initializeRuleClasses(ruleClassBuilder);
}
this.ruleClassProvider = ruleClassBuilder.build();
}
/**
* Converts the WORKSPACE file content into an ExternalPackage.
*/
public ExternalPackage parse(Path workspacePath) {
resolver.addHeader(workspacePath.getPathString());
ExternalPackage.Builder builder = new ExternalPackage.Builder(workspacePath);
WorkspaceFactory parser = new WorkspaceFactory(builder, ruleClassProvider);
try {
parser.parse(ParserInputSource.create(workspacePath));
} catch (IOException | InterruptedException e) {
handler.handle(Event.error(Location.fromFile(workspacePath), e.getMessage()));
}
return builder.build();
}
/**
* Calculates transitive dependencies of the given //external package.
*/
public void resolveTransitiveDependencies(ExternalPackage externalPackage) {
Location location = Location.fromFile(externalPackage.getFilename());
for (Target target : externalPackage.getTargets()) {
// Targets are //external:foo.
if (target.getTargetKind().startsWith("bind")
|| target.getTargetKind().startsWith("source ")) {
continue;
} else if (target.getTargetKind().startsWith("maven_jar ")) {
PackageIdentifier.RepositoryName repositoryName;
try {
repositoryName = PackageIdentifier.RepositoryName.create("@" + target.getName());
} catch (TargetParsingException e) {
handler.handle(Event.error(location, "Invalid repository name for " + target + ": "
+ e.getMessage()));
return;
}
com.google.devtools.build.lib.packages.Rule workspaceRule =
externalPackage.getRepositoryInfo(repositoryName);
DefaultModelResolver modelResolver = resolver.getModelResolver();
AttributeMap attributeMap = AggregatingAttributeMapper.of(workspaceRule);
Rule rule;
try {
if (attributeMap.has("artifact", Type.STRING)
&& !attributeMap.get("artifact", Type.STRING).isEmpty()) {
rule = new Rule(attributeMap.get("artifact", Type.STRING));
} else {
rule = new Rule(attributeMap.get("group_id", Type.STRING) + ":"
+ attributeMap.get("artifact_id", Type.STRING) + ":"
+ attributeMap.get("version", Type.STRING));
}
if (attributeMap.has("repository", Type.STRING)
&& !attributeMap.get("repository", Type.STRING).isEmpty()) {
modelResolver.addUserRepository(attributeMap.get("repository", Type.STRING));
rule.setRepository(attributeMap.get("repository", Type.STRING), handler);
}
} catch (Rule.InvalidRuleException e) {
handler.handle(Event.error(location, "Couldn't get attribute: " + e.getMessage()));
return;
}
ModelSource modelSource;
try {
modelSource = modelResolver.resolveModel(
rule.groupId(), rule.artifactId(), rule.version());
} catch (UnresolvableModelException e) {
handler.handle(Event.error(
"Could not resolve model for " + target + ": " + e.getMessage()));
continue;
}
resolver.resolveEffectiveModel(modelSource);
} else {
handler.handle(Event.warn(location, "Cannot fetch transitive dependencies for " + target
+ " yet, skipping"));
}
}
}
}