aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/analysis/SymlinkTreeAction.java
blob: 56b5455a42c6a95ab4cd4773217ee460135418ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// 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.analysis;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.AbstractAction;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionExecutionException;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Executor;
import com.google.devtools.build.lib.actions.ResourceSet;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.util.Preconditions;
import javax.annotation.Nullable;

/**
 * Action responsible for the symlink tree creation.
 * Used to generate runfiles and fileset symlink farms.
 */
@Immutable
public final class SymlinkTreeAction extends AbstractAction {

  private static final String GUID = "63412bda-4026-4c8e-a3ad-7deb397728d4";

  private final Artifact inputManifest;
  private final Artifact outputManifest;
  private final boolean filesetTree;
  private final ImmutableMap<String, String> shellEnviroment;
  private final boolean enableRunfiles;

  /**
   * Creates SymlinkTreeAction instance.
   *  @param owner action owner
   * @param inputManifest the input runfiles manifest
   * @param artifactMiddleman the middleman artifact representing all the files the symlinks
   *                          point to (on Windows we need to know if the target of a "symlink" is
   *                          a directory or a file so we need to build it before)
   * @param outputManifest the generated symlink tree manifest
   *                       (must have "MANIFEST" base name). Symlink tree root
   *                       will be set to the artifact's parent directory.
   * @param filesetTree true if this is fileset symlink tree,
   * @param enableRunfiles true is the actual symlink tree needs to be created.
   */
  public SymlinkTreeAction(
      ActionOwner owner,
      Artifact inputManifest,
      @Nullable Artifact artifactMiddleman,
      Artifact outputManifest,
      boolean filesetTree,
      ImmutableMap<String, String> shellEnvironment,
      boolean enableRunfiles) {
    super(owner, computeInputs(inputManifest, artifactMiddleman), ImmutableList.of(outputManifest));
    Preconditions.checkArgument(outputManifest.getPath().getBaseName().equals("MANIFEST"));
    this.inputManifest = inputManifest;
    this.outputManifest = outputManifest;
    this.filesetTree = filesetTree;
    this.shellEnviroment = shellEnvironment;
    this.enableRunfiles = enableRunfiles;
  }

  private static ImmutableList<Artifact> computeInputs(
      Artifact inputManifest, Artifact artifactMiddleman) {
    ImmutableList.Builder<Artifact> result = ImmutableList.<Artifact>builder()
        .add(inputManifest);
    if (artifactMiddleman != null
        && !artifactMiddleman.getPath().getFileSystem().supportsSymbolicLinksNatively()) {
      result.add(artifactMiddleman);
    }
    return result.build();
  }

  public Artifact getInputManifest() {
    return inputManifest;
  }

  public Artifact getOutputManifest() {
    return outputManifest;
  }

  public boolean isFilesetTree() {
    return filesetTree;
  }

  @Override
  public String getMnemonic() {
    return "SymlinkTree";
  }

  @Override
  protected String getRawProgressMessage() {
    return (filesetTree ? "Creating Fileset tree " : "Creating runfiles tree ")
        + outputManifest.getExecPath().getParentDirectory().getPathString();
  }

  @Override
  protected String computeKey() {
    Fingerprint f = new Fingerprint();
    f.addString(GUID);
    f.addInt(filesetTree ? 1 : 0);
    return f.hexDigestAndReset();
  }

  @Override
  public ResourceSet estimateResourceConsumption(Executor executor) {
    return ResourceSet.ZERO;
  }

  @Override
  public void execute(
      ActionExecutionContext actionExecutionContext)
          throws ActionExecutionException, InterruptedException {
    actionExecutionContext
        .getExecutor()
        .getContext(SymlinkTreeActionContext.class)
        .createSymlinks(this, actionExecutionContext, shellEnviroment, enableRunfiles);
  }
}