// Copyright 2014 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.lib.analysis;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.BaseSpawn;
import com.google.devtools.build.lib.analysis.actions.FileWriteAction;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.syntax.Label;
import com.google.devtools.build.lib.syntax.SkylarkCallable;
import com.google.devtools.build.lib.syntax.SkylarkModule;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* Provides shared functionality for parameterized command-line launching
* e.g. {@link com.google.devtools.build.lib.view.genrule.GenRule}
* Also used by {@link com.google.devtools.build.lib.rules.extra.ExtraActionFactory}.
*
* Two largely independent separate sets of functionality are provided:
* 1- string interpolation for {@code $(location[s] ...)} and {@code $(MakeVariable)}
* 2- a utility to build potentially large command lines (presumably made of multiple commands),
* that if presumed too large for the kernel's taste can be dumped into a shell script
* that will contain the same commands,
* at which point the shell script is added to the list of inputs.
*/
@SkylarkModule(name = "command_helper",
doc = "Experimental. The API will change in the future. "
+ "A helper class to create shell commands.")
public final class CommandHelper {
/**
* Maximum total command-line length, in bytes, not counting "/bin/bash -c ".
* If the command is very long, then we write the command to a script file,
* to avoid overflowing any limits on command-line length.
* For short commands, we just use /bin/bash -c command.
*/
@VisibleForTesting
public static int maxCommandLength = 64000;
/**
* A map of remote path prefixes and corresponding runfiles manifests for tools
* used by this rule.
*/
private final ImmutableMap remoteRunfileManifestMap;
/**
* Use labelMap for heuristically expanding labels (does not include "outs")
* This is similar to heuristic location expansion in LocationExpander
* and should be kept in sync.
*/
private final ImmutableMap