|  | // Copyright 2018 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.sandbox; | 
|  |  | 
|  | import com.google.common.collect.ImmutableList; | 
|  | import com.google.common.collect.ImmutableMap; | 
|  | import com.google.devtools.build.lib.exec.TreeDeleter; | 
|  | import com.google.devtools.build.lib.sandbox.SandboxHelpers.SandboxInputs; | 
|  | import com.google.devtools.build.lib.sandbox.SandboxHelpers.SandboxOutputs; | 
|  | import com.google.devtools.build.lib.vfs.FileStatus; | 
|  | import com.google.devtools.build.lib.vfs.FileSystemUtils; | 
|  | import com.google.devtools.build.lib.vfs.Path; | 
|  | import com.google.devtools.build.lib.vfs.Symlinks; | 
|  | import java.io.IOException; | 
|  | import java.util.Set; | 
|  | import javax.annotation.Nullable; | 
|  |  | 
|  | /** | 
|  | * Creates an execRoot for a Spawn that contains input files as copies from their original source. | 
|  | */ | 
|  | public class CopyingSandboxedSpawn extends AbstractContainerizingSandboxedSpawn { | 
|  | private final Runnable successCallback; | 
|  |  | 
|  | public CopyingSandboxedSpawn( | 
|  | Path sandboxPath, | 
|  | Path sandboxExecRoot, | 
|  | ImmutableList<String> arguments, | 
|  | ImmutableMap<String, String> environment, | 
|  | SandboxInputs inputs, | 
|  | SandboxOutputs outputs, | 
|  | Set<Path> writableDirs, | 
|  | TreeDeleter treeDeleter, | 
|  | @Nullable Path sandboxDebugPath, | 
|  | @Nullable Path statisticsPath, | 
|  | Runnable successCallback, | 
|  | String mnemonic) { | 
|  | super( | 
|  | sandboxPath, | 
|  | sandboxExecRoot, | 
|  | arguments, | 
|  | environment, | 
|  | inputs, | 
|  | outputs, | 
|  | writableDirs, | 
|  | treeDeleter, | 
|  | sandboxDebugPath, | 
|  | statisticsPath, | 
|  | mnemonic); | 
|  | this.successCallback = successCallback; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public void copyOutputs(Path execRoot) throws IOException { | 
|  | successCallback.run(); | 
|  | super.copyOutputs(execRoot); | 
|  | } | 
|  |  | 
|  | @Override | 
|  | protected void copyFile(Path source, Path target) throws IOException { | 
|  | FileStatus stat = source.stat(Symlinks.NOFOLLOW); | 
|  | if (stat.isSymbolicLink() || stat.isFile()) { | 
|  | FileSystemUtils.copyFile(source, target); | 
|  | } else if (stat.isDirectory()) { | 
|  | target.createDirectory(); | 
|  | FileSystemUtils.copyTreesBelow(source, target, Symlinks.NOFOLLOW); | 
|  | } | 
|  | } | 
|  | } |