// 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.runtime.commands; import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.pkgcache.PackageCacheOptions; import com.google.devtools.build.lib.pkgcache.PathPackageLocator; import com.google.devtools.build.lib.runtime.BlazeCommand; import com.google.devtools.build.lib.runtime.BlazeRuntime; import com.google.devtools.build.lib.runtime.CommandEnvironment; import com.google.devtools.build.lib.runtime.CommonCommandOptions; import com.google.devtools.build.lib.runtime.ProjectFile; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.common.options.OptionPriority; import com.google.devtools.common.options.OptionsParser; import com.google.devtools.common.options.OptionsParsingException; import com.google.devtools.common.options.OptionsProvider; import java.util.List; /** * Provides support for implementations for {@link BlazeCommand} to work with {@link ProjectFile}. */ public final class ProjectFileSupport { static final String PROJECT_FILE_PREFIX = "+"; private ProjectFileSupport() {} /** * Reads any project files specified on the command line and updates the options parser * accordingly. If project files cannot be read or if they contain unparsable options, or if they * are not enabled, then it throws an exception instead. */ public static void handleProjectFiles(CommandEnvironment env, OptionsParser optionsParser, String command) throws OptionsParsingException { BlazeRuntime runtime = env.getRuntime(); List<String> targets = optionsParser.getResidue(); ProjectFile.Provider projectFileProvider = runtime.getProjectFileProvider(); if (projectFileProvider != null && !targets.isEmpty() && targets.get(0).startsWith(PROJECT_FILE_PREFIX)) { if (targets.size() > 1) { throw new OptionsParsingException("Cannot handle more than one +<file> argument yet"); } if (!optionsParser.getOptions(CommonCommandOptions.class).allowProjectFiles) { throw new OptionsParsingException("project file support is not enabled"); } // TODO(bazel-team): This is currently treated as a path relative to the workspace - if the // cwd is a subdirectory of the workspace, that will be surprising, and we should interpret it // relative to the cwd instead. PathFragment projectFilePath = PathFragment.create(targets.get(0).substring(1)); List<Path> packagePath = PathPackageLocator.create( env.getOutputBase(), optionsParser.getOptions(PackageCacheOptions.class).packagePath, env.getReporter(), env.getWorkspace(), env.getWorkingDirectory()).getPathEntries(); ProjectFile projectFile = projectFileProvider.getProjectFile( env.getWorkingDirectory(), packagePath, projectFilePath); env.getReporter().handle(Event.info("Using " + projectFile.getName())); optionsParser.parse( OptionPriority.RC_FILE, projectFile.getName(), projectFile.getCommandLineFor(command)); env.getEventBus().post(new GotProjectFileEvent(projectFile.getName())); } } /** * Returns a list of targets from the options residue. If a project file is supplied as the first * argument, it will be ignored, on the assumption that handleProjectFiles() has been called to * process it. */ public static List<String> getTargets(BlazeRuntime runtime, OptionsProvider options) { List<String> targets = options.getResidue(); if (runtime.getProjectFileProvider() != null && !targets.isEmpty() && targets.get(0).startsWith(PROJECT_FILE_PREFIX)) { return targets.subList(1, targets.size()); } return targets; } }