// 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.actions;

import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Streams;
import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.concurrent.ThreadSafety;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.skyframe.SkyFunctions;
import com.google.devtools.build.lib.skyframe.serialization.DeserializationContext;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec;
import com.google.devtools.build.lib.skyframe.serialization.SerializationContext;
import com.google.devtools.build.lib.skyframe.serialization.SerializationException;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
import com.google.devtools.build.lib.starlarkbuildapi.FileApi;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.skyframe.ShareabilityOfValue;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.CodedOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Printer;
import net.starlark.java.eval.Starlark;

/**
 * An Artifact represents a file used by the build system, whether it's a source file or a derived
 * (output) file. Not all Artifacts have a corresponding FileTarget object in the <code>
 * build.lib.packages</code> API: for example, low-level intermediaries internal to a given rule,
 * such as a Java class files or C++ object files. However all FileTargets have a corresponding
 * Artifact.
 *
 * <p>In any given call to SkyframeExecutor#buildArtifacts(), no two Artifacts in the action graph
 * may refer to the same path.
 *
 * <p>Artifacts generally fall into two classifications, source and derived, but there exist a few
 * other cases that are fuzzy and difficult to classify. The following cases exist:
 *
 * <ul>
 *   <li>Well-formed source Artifacts will have null generating Actions and a root that is
 *       orthogonal to execRoot. (With the root coming from the package path.)
 *   <li>Well-formed derived Artifacts will have non-null generating Actions, and a root that is
 *       below execRoot.
 *   <li>Symlinked include source Artifacts under the output/include tree will appear to be derived
 *       artifacts with null generating Actions.
 *   <li>Some derived Artifacts, mostly in the genfiles tree and mostly discovered during include
 *       validation, will also have null generating Actions.
 * </ul>
 *
 * In the usual case, an Artifact represents a single file. However, an Artifact may also represent
 * the following:
 *
 * <ul>
 *   <li>A TreeArtifact, which is a directory containing a tree of unknown {@link Artifact}s. In the
 *       future, Actions will be able to examine these files as inputs and declare them as outputs
 *       at execution time, but this is not yet implemented. This is used for Actions where the
 *       inputs and/or outputs might not be discoverable except during Action execution.
 *   <li>A directory of unknown contents, but not a TreeArtifact. This is a legacy facility and
 *       should not be used by any new rule implementations. In particular, the file system cache
 *       integrity checks fail for directories.
 *   <li>A middleman special Artifact, which may be expanded using a {@link ArtifactExpander} at
 *       Action execution time. This is used by a handful of rules to save memory.
 *   <li>A 'constant metadata' special Artifact. These represent real files, changes to which are
 *       ignored by the build system. They are useful for files which change frequently but do not
 *       affect the result of a build, such as timestamp files.
 *   <li>A 'Fileset' special Artifact. This is a legacy type of Artifact and should not be used by
 *       new rule implementations.
 *   <li>A 'symlink' special Artifact. While a symlink can also be represented by a regular
 *       Artifact, using a symlink special Artifact would result in deriving the Artifact's SkyValue
 *       from the symlinks themselves (lstat, not stat), and not following the symlinks like in
 *       regular Artifacts. The underlying symlink can be unresolved, otherwise known as a dangling
 *       symlink.
 * </ul>
 *
 * <p>While Artifact implements {@link SkyKey} for memory-saving purposes, Skyframe requests
 * involving artifacts should always go through {@link Artifact#key} since ordinary derived
 * artifacts should not be requested directly from Skyframe.
 */
public abstract class Artifact
    implements FileType.HasFileType,
        ActionInput,
        FileApi,
        Comparable<Artifact>,
        CommandLineItem,
        SkyKey {

  public static final Depset.ElementType TYPE = Depset.ElementType.of(Artifact.class);

  /** Compares artifact according to their exec paths. Sorts null values first. */
  @SerializationConstant
  @SuppressWarnings("ReferenceEquality") // "a == b" is an optimization
  public static final Comparator<Artifact> EXEC_PATH_COMPARATOR =
      (a, b) -> {
        if (a == b) {
          return 0;
        } else if (a == null) {
          return -1;
        } else if (b == null) {
          return 1;
        } else {
          return a.execPath.compareTo(b.execPath);
        }
      };

  /** Compares artifact according to their root relative paths. Sorts null values first. */
  @SuppressWarnings("ReferenceEquality") // "a == b" is an optimization
  public static final Comparator<Artifact> ROOT_RELATIVE_PATH_COMPARATOR =
      (a, b) -> {
        if (a == b) {
          return 0;
        } else if (a == null) {
          return -1;
        } else if (b == null) {
          return 1;
        } else {
          int result = a.getRootRelativePath().compareTo(b.getRootRelativePath());
          if (result == 0) {
            // Use the full exec path as a fallback if the root-relative paths are the same, thus
            // avoiding problems when ImmutableSortedMaps are switched from EXEC_PATH_COMPARATOR.
            return a.execPath.compareTo(b.execPath);
          } else {
            return result;
          }
        }
      };

  /**
   * {@link com.google.devtools.build.lib.skyframe.ArtifactFunction} does direct filesystem access
   * without declaring Skyframe dependencies if the artifact is a source directory. However, that
   * filesystem access is not invalidated on incremental builds, and we have no plans to fix it,
   * since general consumption of source directories in this way is unsound. Therefore no new bugs
   * are created by declaring {@link com.google.devtools.build.lib.skyframe.ArtifactFunction} to be
   * hermetic.
   *
   * <p>TODO(janakr): Avoid this issue entirely by giving {@link SourceArtifact} its own {@code
   * SkyFunction}. Then we can just declare that function to be non-hermetic. That will also save
   * memory since we can make mandatory source artifacts their own SkyKeys!
   */
  public static final SkyFunctionName ARTIFACT = SkyFunctionName.createHermetic("ARTIFACT");

  /**
   * Returns a {@link SkyKey} that, when built, will produce this artifact. For source artifacts and
   * generated artifacts that may aggregate other artifacts, returns the artifact itself. For normal
   * generated artifacts, returns the key of the generating action.
   *
   * <p>Callers should use this method (or the related ones below) in preference to directly
   * requesting an {@link Artifact} to be built by Skyframe, since ordinary derived artifacts should
   * never be directly built by Skyframe.
   */
  @ThreadSafety.ThreadSafe
  public static SkyKey key(Artifact artifact) {
    if (artifact.isTreeArtifact()
        || artifact.isMiddlemanArtifact()
        || !artifact.hasKnownGeneratingAction()) {
      return artifact;
    }

    return ((DerivedArtifact) artifact).getGeneratingActionKey();
  }

  public static Collection<SkyKey> keys(Collection<Artifact> artifacts) {
    return artifacts instanceof List
        ? keys((List<Artifact>) artifacts)
        // Use Collections2 instead of Iterables#transform to ensure O(1) size().
        : Collections2.transform(artifacts, Artifact::key);
  }

  public static List<SkyKey> keys(List<Artifact> artifacts) {
    return Lists.transform(artifacts, Artifact::key);
  }

  @Override
  public int compareTo(Artifact o) {
    return EXEC_PATH_COMPARATOR.compare(this, o);
  }

  /** An object that can expand middleman and tree artifacts. */
  public interface ArtifactExpander {

    /**
     * Expands the given artifact, and populates "output" with the result.
     *
     * <p>{@code artifact.isMiddlemanArtifact() || artifact.isTreeArtifact()} must be true. Only
     * middlemen and tree artifacts are expanded.
     */
    void expand(Artifact artifact, Collection<? super Artifact> output);

    /**
     * Returns the expansion of Fileset for the given artifact.
     *
     * @param artifact {@code artifact.isFileset()} must be true.
     * @throws MissingExpansionException if the expander is missing data needed to expand provided
     *     fileset.
     */
    default ImmutableList<FilesetOutputSymlink> getFileset(Artifact artifact)
        throws MissingExpansionException {
      throw new MissingExpansionException("Cannot expand fileset " + artifact);
    }

    /**
     * Return an {@link ArchivedTreeArtifact} for a provided {@linkplain SpecialArtifact tree
     * artifact} if one is available.
     *
     * <p>The {@linkplain ArchivedTreeArtifact archived tree artifact} can be used instead of the
     * tree artifact expansion.
     */
    @Nullable
    default ArchivedTreeArtifact getArchivedTreeArtifact(SpecialArtifact treeArtifact) {
      return null;
    }
  }

  /**
   * Exception thrown when attempting to {@linkplain ArtifactExpander expand} an artifact for which
   * we do not have the necessary data.
   */
  public static final class MissingExpansionException extends Exception {

    public MissingExpansionException(String message) {
      super(message);
    }
  }

  /** Implementation of {@link ArtifactExpander} */
  public static class ArtifactExpanderImpl implements ArtifactExpander {
    private final Map<Artifact, ImmutableCollection<? extends Artifact>> expandedInputs;
    private final Map<SpecialArtifact, ArchivedTreeArtifact> archivedTreeArtifacts;
    private final Map<Artifact, ImmutableList<FilesetOutputSymlink>> expandedFilesets;

    public ArtifactExpanderImpl(
        Map<Artifact, ImmutableCollection<? extends Artifact>> expandedInputs,
        Map<SpecialArtifact, ArchivedTreeArtifact> archivedTreeArtifacts,
        Map<Artifact, ImmutableList<FilesetOutputSymlink>> expandedFilesets) {
      this.expandedInputs = expandedInputs;
      this.archivedTreeArtifacts = archivedTreeArtifacts;
      this.expandedFilesets = expandedFilesets;
    }

    @Override
    public void expand(Artifact artifact, Collection<? super Artifact> output) {
      Preconditions.checkState(
          artifact.isMiddlemanArtifact() || artifact.isTreeArtifact(), artifact);
      ImmutableCollection<? extends Artifact> result = expandedInputs.get(artifact);
      if (result != null) {
        output.addAll(result);
      }
    }

    @Override
    public ImmutableList<FilesetOutputSymlink> getFileset(Artifact artifact)
        throws MissingExpansionException {
      Preconditions.checkState(artifact.isFileset());
      ImmutableList<FilesetOutputSymlink> filesetLinks = expandedFilesets.get(artifact);
      if (filesetLinks == null) {
        throw new MissingExpansionException("Missing expansion for fileset: " + artifact);
      }
      return filesetLinks;
    }

    @Override
    public ArchivedTreeArtifact getArchivedTreeArtifact(SpecialArtifact treeArtifact) {
      return archivedTreeArtifacts.get(treeArtifact);
    }
  }

  /** A Predicate that evaluates to true if the Artifact is not a middleman artifact. */
  public static final Predicate<Artifact> MIDDLEMAN_FILTER = input -> !input.isMiddlemanArtifact();

  private final ArtifactRoot root;

  private final int hashCode;
  private final PathFragment execPath;

  private Artifact(ArtifactRoot root, PathFragment execPath) {
    Preconditions.checkNotNull(root);
    // The ArtifactOwner is not part of this computation because it is very rare that two Artifacts
    // have the same execPath and different owners, so a collision is fine there. If this is
    // changed, OwnerlessArtifactWrapper must also be changed.
    this.hashCode = execPath.hashCode();
    this.root = root;
    this.execPath = execPath;
  }

  /**
   * An artifact corresponding to a file in the output tree, generated by an {@link Action}, but for
   * which the generating action is unknown (may have been created as an undeclared "side effect" of
   * another action).
   *
   * <p>This artifact type defined for compatibility with the Ninja build system.
   *
   * <p>Only use this type in rare cases, and only when there is certainty that the artifact is
   * actually generated by an action in the build (for example, when another action declares it as
   * an explicit dependency in a post-execution .d file). These artifacts are indicative of
   * underspecified, incomplete builds, and may in worst cases be indicative of incorrect builds.
   */
  @Immutable
  public static final class NinjaMysteryArtifact extends Artifact {
    public NinjaMysteryArtifact(ArtifactRoot root, PathFragment execPath) {
      super(root, execPath);
    }

    @Override
    public PathFragment getRootRelativePath() {
      return getExecPath().relativeTo(getRoot().getExecPath());
    }

    @Override
    boolean ownersEqual(Artifact other) {
      return true;
    }

    @Override
    public ArtifactOwner getArtifactOwner() {
      return ArtifactOwner.NULL_OWNER;
    }

    @Override
    public Label getOwnerLabel() {
      return ArtifactOwner.NULL_OWNER.getLabel();
    }

    @Override
    public boolean hasKnownGeneratingAction() {
      return false;
    }
  }

  /** An artifact corresponding to a file in the output tree, generated by an {@link Action}. */
  public static class DerivedArtifact extends Artifact {

    /**
     * An {@link ActionLookupKey} until {@link #setGeneratingActionKey} is set, at which point it is
     * an {@link ActionLookupData}, whose {@link ActionLookupData#getActionLookupKey} will be the
     * same as the original value of owner.
     *
     * <p>We overload this field in order to save memory.
     */
    private Object owner;

    /**
     * Content-based output paths are experimental. Only derived artifacts that are explicitly opted
     * in by their creating rules should use them and only when {@link
     * com.google.devtools.build.lib.analysis.config.BuildConfigurationValue#useContentBasedOutputPaths}
     * is on.
     */
    private final boolean contentBasedPath;

    /** Standard factory method for derived artifacts. */
    public static DerivedArtifact create(
        ArtifactRoot root, PathFragment execPath, ActionLookupKey owner) {
      return create(root, execPath, owner, /*contentBasedPath=*/ false);
    }

    /**
     * Same as {@link #create(ArtifactRoot, PathFragment, ActionLookupKey)} but includes the option
     * to use a content-based path for this artifact (see {@link
     * com.google.devtools.build.lib.analysis.config.BuildConfigurationValue#useContentBasedOutputPaths}).
     */
    public static DerivedArtifact create(
        ArtifactRoot root, PathFragment execPath, ActionLookupKey owner, boolean contentBasedPath) {
      return new DerivedArtifact(root, execPath, owner, contentBasedPath);
    }

    private DerivedArtifact(ArtifactRoot root, PathFragment execPath, Object owner) {
      this(root, execPath, owner, /*contentBasedPath=*/ false);
    }

    private DerivedArtifact(
        ArtifactRoot root, PathFragment execPath, Object owner, boolean contentBasedPath) {
      super(root, execPath);
      Preconditions.checkState(
          !root.getExecPath().isEmpty(), "Derived root has no exec path: %s, %s", root, execPath);
      this.owner = Preconditions.checkNotNull(owner);
      this.contentBasedPath = contentBasedPath;
    }

    /**
     * Called when a configured target's actions are being collected. {@code generatingActionKey}
     * must have the same owner as this artifact's current {@link #getArtifactOwner}.
     */
    @VisibleForTesting
    public final void setGeneratingActionKey(ActionLookupData generatingActionKey) {
      Preconditions.checkState(
          this.owner != OMITTED_FOR_SERIALIZATION, "Owner was omitted for serialization: %s", this);
      Preconditions.checkState(
          this.owner instanceof ActionLookupKey,
          "Already set generating action key: %s (%s %s)",
          this,
          this.owner,
          generatingActionKey);
      Preconditions.checkState(
          Preconditions.checkNotNull(generatingActionKey, this).getActionLookupKey().equals(owner),
          "Owner of generating action key not same as artifact's owner: %s (%s %s)",
          this,
          this.owner,
          generatingActionKey);
      this.owner = generatingActionKey;
    }

    @VisibleForTesting
    public final boolean hasGeneratingActionKey() {
      return this.owner instanceof ActionLookupData;
    }

    /** Can only be called once {@link #setGeneratingActionKey} is called. */
    public final ActionLookupData getGeneratingActionKey() {
      Preconditions.checkState(owner instanceof ActionLookupData, "Bad owner: %s %s", this, owner);
      return (ActionLookupData) owner;
    }

    @Override
    public final ActionLookupKey getArtifactOwner() {
      Preconditions.checkState(
          this.owner != OMITTED_FOR_SERIALIZATION, "Owner was omitted for serialization: %s", this);
      return owner instanceof ActionLookupData
          ? getGeneratingActionKey().getActionLookupKey()
          : (ActionLookupKey) owner;
    }

    @Override
    public final Label getOwnerLabel() {
      return getArtifactOwner().getLabel();
    }

    @Override
    public final String toDebugString() {
      if (hasGeneratingActionKey() || owner == OMITTED_FOR_SERIALIZATION) {
        return super.toDetailString() + " (" + owner + ")";
      }
      return super.toDebugString();
    }

    @Override
    public final PathFragment getRootRelativePath() {
      return getExecPath().relativeTo(getRoot().getExecPath());
    }

    @Override
    final boolean ownersEqual(Artifact other) {
      DerivedArtifact that = (DerivedArtifact) other;
      if (!(this.owner instanceof ActionLookupData) || !(that.owner instanceof ActionLookupData)) {
        // Happens when at least one of these artifacts hasn't had its generating action key set
        // yet, so its configured target is still being analyzed. Tolerate.
        return this.getArtifactOwner().equals(that.getArtifactOwner());
      }
      return this.owner.equals(that.owner);
    }

    @Override
    public boolean contentBasedPath() {
      return contentBasedPath;
    }
  }

  /** Supplies {@link SourceArtifact} instances and allows for interning of derived artifacts. */
  public interface ArtifactSerializationContext {

    SourceArtifact getSourceArtifact(PathFragment execPath, Root root, ArtifactOwner owner);

    /**
     * Whether to include the generating action key when serializing the given derived artifact.
     *
     * <p>If {@code false} is returned, upon deserialization the generating action key is replaced
     * with the marker {@link #OMITTED_FOR_SERIALIZATION}. The artifact is then only intended for
     * use with {@link #equalsWithoutOwner} or {@link OwnerlessArtifactWrapper} - any operation
     * accessing the generating action key will fail.
     */
    default boolean includeGeneratingActionKey(DerivedArtifact artifact) {
      return true;
    }

    default DerivedArtifact intern(DerivedArtifact original) {
      return original;
    }
  }

  /**
   * Marker stored in place of the generating action key for deserialized artifacts when {@link
   * ArtifactSerializationContext#includeGeneratingActionKey} is {@code false}.
   */
  @SerializationConstant @VisibleForSerialization
  static final Object OMITTED_FOR_SERIALIZATION =
      new Object() {
        @Override
        public String toString() {
          return "OMITTED_FOR_SERIALIZATION";
        }
      };

  @SuppressWarnings("unused") // Codec used by reflection.
  private static final class DerivedArtifactCodec implements ObjectCodec<DerivedArtifact> {

    @Override
    public Class<DerivedArtifact> getEncodedClass() {
      return DerivedArtifact.class;
    }

    @Override
    public void serialize(
        SerializationContext context, DerivedArtifact obj, CodedOutputStream codedOut)
        throws SerializationException, IOException {
      context.serialize(obj.getRoot(), codedOut);
      context.serialize(obj.getRootRelativePath(), codedOut);
      context.serialize(getGeneratingActionKeyForSerialization(obj, context), codedOut);
    }

    @Override
    public DerivedArtifact deserialize(DeserializationContext context, CodedInputStream codedIn)
        throws SerializationException, IOException {
      ArtifactRoot root = context.deserialize(codedIn);
      PathFragment rootRelativePath = context.deserialize(codedIn);
      Object generatingActionKey = context.deserialize(codedIn);
      DerivedArtifact artifact =
          new DerivedArtifact(
              root,
              getExecPathForDeserialization(root, rootRelativePath, generatingActionKey),
              generatingActionKey);
      return context.getDependency(ArtifactSerializationContext.class).intern(artifact);
    }
  }

  private static Object getGeneratingActionKeyForSerialization(
      DerivedArtifact artifact, SerializationContext context) {
    return context
            .getDependency(ArtifactSerializationContext.class)
            .includeGeneratingActionKey(artifact)
        ? artifact.getGeneratingActionKey()
        : OMITTED_FOR_SERIALIZATION;
  }

  private static PathFragment getExecPathForDeserialization(
      ArtifactRoot root, PathFragment rootRelativePath, Object generatingActionKey) {
    Preconditions.checkArgument(
        !root.isSourceRoot(),
        "Root not derived: %s (rootRelativePath=%s, generatingActionKey=%s)",
        root,
        rootRelativePath,
        generatingActionKey);
    Preconditions.checkArgument(
        root.getRoot().isAbsolute() == rootRelativePath.isAbsolute(),
        "Illegal root relative path: %s (root=%s, generatingActionKey=%s)",
        rootRelativePath,
        root,
        generatingActionKey);
    return root.getExecPath().getRelative(rootRelativePath);
  }

  public final Path getPath() {
    return root.getRoot().getRelative(getRootRelativePath());
  }

  public boolean hasParent() {
    return getParent() != null;
  }

  /**
   * Returns the parent Artifact containing this Artifact. Artifacts without parents shall return
   * null.
   */
  @Nullable
  public SpecialArtifact getParent() {
    return null;
  }

  /**
   * Returns the directory name of this artifact, similar to dirname(1).
   *
   * <p> The directory name is always a relative path to the execution directory.
   */
  @Override
  public final String getDirname() {
    PathFragment parent = execPath.getParentDirectory();
    return (parent == null) ? "/" : parent.getSafePathString();
  }

  /**
   * Returns the base file name of this artifact, similar to basename(1).
   */
  @Override
  public final String getFilename() {
    return execPath.getBaseName();
  }

  @Override
  public final String getExtension() {
    return execPath.getFileExtension();
  }

  /**
   * Checks whether this artifact is of the supplied file type.
   *
   * <p>Prefer this method to pulling out strings from the Artifact and passing to {@link
   * FileType#apply(String)} manually. This method has been optimized to generate a minimum of
   * garbage.
   */
  public boolean isFileType(FileType fileType) {
    return fileType.matches(this);
  }

  /** Checks whether this artifact is of one of the types in the supplied set. */
  public boolean isFileType(FileTypeSet fileTypeSet) {
    return fileTypeSet.matches(filePathForFileTypeMatcher());
  }

  @Override
  public final String filePathForFileTypeMatcher() {
    return execPath.filePathForFileTypeMatcher();
  }

  @Override
  public final String expandToCommandLine() {
    return getExecPathString();
  }

  /** Returns the artifact's owning label. May be null. */
  @Nullable
  public final Label getOwner() {
    return getOwnerLabel();
  }

  /**
   * Gets the {@code ActionLookupKey} of the {@code ConfiguredTarget} that owns this artifact, if it
   * was set. Otherwise, this should be a dummy value -- either {@link ArtifactOwner#NULL_OWNER} or
   * a dummy owner set in tests. Such a dummy value should only occur for source artifacts if
   * created without specifying the owner, or for special derived artifacts, such as target
   * completion middleman artifacts, build info artifacts, and the like.
   */
  public abstract ArtifactOwner getArtifactOwner();

  /**
   * Returns the root beneath which this Artifact resides, if any. This may be one of the
   * package-path entries (for source Artifacts), or one of the bin, genfiles or includes dirs (for
   * derived Artifacts). It will always be an ancestor of getPath().
   */
  @Override
  public final ArtifactRoot getRoot() {
    return root;
  }

  @Override
  public final PathFragment getExecPath() {
    return execPath;
  }

  /**
   * Returns the relative path to this artifact relative to its root. It makes no guarantees as to
   * the semantic meaning or the completeness of the returned path value. In other words, no
   * assumptions should be made in terms of where the root portion of the path ends, and the
   * returned value almost always needs to be used in conjunction with its root.
   *
   * <p>{#link Artifact#getOutputDirRelativePath()} is more versatile for general use cases.
   */
  public abstract PathFragment getRootRelativePath();

  /**
   * Returns the fully-qualified package path to this artifact. By "fully-qualified", it means the
   * returned path is prefixed with "external/<repository name>" if this artifact is in an external
   * repository.
   *
   * <p>Do not call this method just because you need a path prefixed with the "external/<repository
   * name>" fragment for external repository artifacts. {@link * Artifact#getOutputDirRelativePath}
   * is the right one to use in almost all cases.
   *
   * @deprecated This method is only to be used for $(location) and getOutputDirRelativePath
   *     implementations.
   */
  @Deprecated
  public PathFragment getPathForLocationExpansion() {
    return getRootRelativePath();
  }

  /**
   * Returns the path to this artifact relative to an output directory, e.g. the bin directory. Note
   * that this is available on every Artifact type, including source artifacts. As a matter of fact,
   * one of its most common use cases is to construct a derived artifact's output path out of a
   * sibling source artifact's by replacing the basename in its output-dir-relative path.
   */
  public PathFragment getOutputDirRelativePath(boolean siblingRepositoryLayout) {
    return getRootRelativePath();
  }

  /**
   * Returns the path to this artifact relative to its repository root. As a result, the returned
   * path always starts with a corresponding package name, if exists.
   */
  public PathFragment getRepositoryRelativePath() {
    PathFragment relativePath = getRootRelativePath();
    // External artifacts under legacy roots are still prefixed with "external/<repo name>".
    if (root.isLegacy() && relativePath.startsWith(LabelConstants.EXTERNAL_PATH_PREFIX)) {
      relativePath = relativePath.subFragment(2);
    }
    return relativePath;
  }

  /** Returns this.getExecPath().getPathString(). */
  @Override
  public final String getExecPathString() {
    return execPath.getPathString();
  }

  public final String getRootRelativePathString() {
    return getRootRelativePath().getPathString();
  }

  public final String getRepositoryRelativePathString() {
    return getRepositoryRelativePath().getPathString();
  }

  @Override
  public boolean isSymlink() {
    return false;
  }

  /**
   * Returns the path of this Artifact relative to this containing Artifact. Since ordinary
   * Artifacts correspond to only one Artifact -- itself -- for ordinary Artifacts, this just
   * returns the empty path. For special Artifacts, returns {@code null}.
   */
  public PathFragment getParentRelativePath() {
    return PathFragment.EMPTY_FRAGMENT;
  }

  @Override
  public String getTreeRelativePathString() throws EvalException {
    throw Starlark.errorf(
        "tree_relative_path not allowed for files that are not tree artifact files.");
  }

  /**
   * Returns true iff this is a source Artifact as determined by its path and root relationships.
   * Note that this will report all Artifacts in the output tree, including in the include symlink
   * tree, as non-source.
   *
   * <p>An {@link Artifact} is a {@link SourceArtifact} iff this returns true, and a {@link
   * DerivedArtifact} otherwise.
   */
  @Override
  public final boolean isSourceArtifact() {
    return root.isSourceRoot();
  }

  /**
   * Returns true iff this artifact has a generating action, and that generating action is known.
   */
  public boolean hasKnownGeneratingAction() {
    return !isSourceArtifact();
  }

  /**
   * Returns true iff this is a middleman Artifact as determined by its root.
   *
   * <p>If true, this artifact is necessarily a {@link DerivedArtifact}.
   */
  public final boolean isMiddlemanArtifact() {
    return root.isMiddlemanRoot();
  }

  /**
   * Returns true iff this is a TreeArtifact representing a directory tree containing Artifacts.
   *
   * <p>if true, this artifact is necessarily a {@link SpecialArtifact} with type {@link
   * SpecialArtifactType#TREE}.
   */
  public boolean isTreeArtifact() {
    return false;
  }

  /**
   * Returns {@code true} if this is a {@link TreeFileArtifact} that was created by an action which
   * declared an output directory, as opposed to an action that was generated by an action template
   * expansion.
   *
   * <p>Such artifacts should always be stored within a {@link
   * com.google.devtools.build.lib.skyframe.TreeArtifactValue} representing the declared directory
   * and all children, not individually like other derived artifacts.
   */
  public boolean isChildOfDeclaredDirectory() {
    return false;
  }

  /**
   * Returns whether the artifact represents a Fileset.
   *
   * <p>if true, this artifact is necessarily a {@link SpecialArtifact} with type {@link
   * SpecialArtifactType#FILESET}.
   */
  public boolean isFileset() {
    return false;
  }

  /** The disjunction of {@link #isTreeArtifact} and {@link #isFileset}. */
  @Override
  public boolean isDirectory() {
    return isTreeArtifact() || isFileset();
  }

  /**
   * Returns true iff metadata cache must return constant metadata for the given artifact.
   *
   * <p>If true, this artifact is necessarily a {@link SpecialArtifact} with type {@link
   * SpecialArtifactType#CONSTANT_METADATA}.
   */
  public boolean isConstantMetadata() {
    return false;
  }

  /**
   * For targets in external repositories, this returns the path the artifact live at in the
   * runfiles tree. For local targets, it returns the rootRelativePath.
   */
  public final PathFragment getRunfilesPath() {
    PathFragment relativePath = getRootRelativePath();
    // Runfile paths for external artifacts should be prefixed with "../<repo name>".
    if (root.isLegacy()) {
      // Root-relative paths of external artifacts under legacy roots are already prefixed with
      // "external/<repo name>". Just replace "external" with "..".
      if (relativePath.startsWith(LabelConstants.EXTERNAL_PATH_PREFIX)) {
        relativePath = relativePath.relativeTo(LabelConstants.EXTERNAL_PATH_PREFIX);
        relativePath = LabelConstants.EXTERNAL_RUNFILES_PATH_PREFIX.getRelative(relativePath);
      }
    } else {
      if (root.isExternal()) {
        // Both external source artifacts and external derived artifacts have their repo name as
        // their 2nd level directory name in their exec paths.
        // i.e. external/<repo name>/... and bazel-out/<repo name>/...
        // This is a pure coincidence, and the below line needs to be updated if any of the
        // directory structures change.
        String repoName = execPath.getSegment(1);
        relativePath =
            LabelConstants.EXTERNAL_RUNFILES_PATH_PREFIX
                .getRelative(repoName)
                .getRelative(relativePath);
      }
    }
    // We can't use root.isExternalSource() here since it needs to handle derived artifacts too.
    return relativePath;
  }

  @Override
  public final String getRunfilesPathString() {
    return getRunfilesPath().getPathString();
  }

  public final String prettyPrint() {
    // toDetailString would probably be more useful to users, but lots of tests rely on the
    // current values.
    return getRootRelativePath().toString();
  }

  @SuppressWarnings("EqualsGetClass") // Distinct classes of Artifact are never equal.
  @Override
  public final boolean equals(Object other) {
    if (this == other) {
      return true;
    }
    if (!(other instanceof Artifact)) {
      return false;
    }
    if (!getClass().equals(other.getClass())) {
      return false;
    }
    Artifact that = (Artifact) other;
    return equalsWithoutOwner(that) && ownersEqual(that);
  }

  final boolean equalsWithoutOwner(Artifact other) {
    return hashCode == other.hashCode && execPath.equals(other.execPath) && root.equals(other.root);
  }

  abstract boolean ownersEqual(Artifact other);

  @Override
  public final int hashCode() {
    // This is just execPath.hashCode() (along with the class). We cache a copy in the Artifact
    // object to reduce LLC misses during operations which build a HashSet out of many Artifacts.
    // This is a slight loss for memory but saves ~1% overall CPU in some real builds.
    return hashCode;
  }

  @Override
  public final String toString() {
    return "File:" + toDetailString();
  }

  /** Returns a string representing the complete artifact path information. */
  public final String toDetailString() {
    if (isSourceArtifact()) {
      // Source Artifact: relPath == execPath, & real path is not under execRoot
      return "[" + root + "]" + getRootRelativePathString();
    } else {
      // Derived Artifact: path and root are under execRoot
      //
      // TODO(blaze-team): this is misleading because execution_root isn't unique. Dig the
      // workspace name out and print that also.
      return "[[<execution_root>]" + root.getExecPath() + "]" + getRootRelativePathString();
    }
  }

  public String toDebugString() {
    if (getOwner() == null || getOwner().toPathFragment().equals(execPath)) {
      return toDetailString();
    }
    return toDetailString() + " (" + getArtifactOwner() + ")";
  }

  @Override
  public final SkyFunctionName functionName() {
    return ARTIFACT;
  }

  /** {@link Artifact#isSourceArtifact() is true.
   *
   * <p>Source artifacts have the property that unlike for output artifacts, direct file system
   * access for their contents should be safe, even in a distributed context.
   *
   * TODO(shahan): move {@link Artifact#getPath} to this subclass.
   */
  public static final class SourceArtifact extends Artifact {
    private final ArtifactOwner owner;

    @VisibleForTesting
    public SourceArtifact(ArtifactRoot root, PathFragment execPath, ArtifactOwner owner) {
      super(root, execPath);
      this.owner = owner;
    }

    /**
     * Source artifacts do not consider their owners in equality checks, since their owners are
     * purely cosmetic.
     */
    @Override
    boolean ownersEqual(Artifact other) {
      return true;
    }

    @Override
    public PathFragment getRootRelativePath() {
      return getRoot().isExternal() ? getExecPath().subFragment(2) : getExecPath();
    }

    @Override
    public PathFragment getPathForLocationExpansion() {
      return getExecPath();
    }

    @Override
    public PathFragment getOutputDirRelativePath(boolean siblingRepositoryLayout) {
      return siblingRepositoryLayout ? getRepositoryRelativePath() : getExecPath();
    }

    @Override
    public PathFragment getRepositoryRelativePath() {
      return getRootRelativePath();
    }

    @Override
    public ArtifactOwner getArtifactOwner() {
      return owner;
    }

    @Override
    public Label getOwnerLabel() {
      return owner.getLabel();
    }

    boolean differentOwnerOrRoot(ArtifactOwner owner, ArtifactRoot root) {
      return !this.owner.equals(owner) || !this.getRoot().equals(root);
    }
  }

  /** {@link ObjectCodec} for {@link SourceArtifact} */
  @SuppressWarnings("unused") // Used by reflection.
  private static final class SourceArtifactCodec implements ObjectCodec<SourceArtifact> {

    @Override
    public Class<SourceArtifact> getEncodedClass() {
      return SourceArtifact.class;
    }

    @Override
    public void serialize(
        SerializationContext context, SourceArtifact obj, CodedOutputStream codedOut)
        throws SerializationException, IOException {
      context.serialize(obj.getExecPath(), codedOut);
      context.serialize(obj.getRoot(), codedOut);
      context.serialize(obj.getArtifactOwner(), codedOut);
    }

    @Override
    public SourceArtifact deserialize(DeserializationContext context, CodedInputStream codedIn)
        throws SerializationException, IOException {
      PathFragment execPath = context.deserialize(codedIn);
      ArtifactRoot artifactRoot = context.deserialize(codedIn);
      ArtifactOwner owner = context.deserialize(codedIn);
      return context
          .getDependency(ArtifactSerializationContext.class)
          .getSourceArtifact(execPath, artifactRoot.getRoot(), owner);
    }
  }

  /**
   * Special artifact types.
   *
   * @see SpecialArtifact
   */
  @VisibleForTesting
  public enum SpecialArtifactType {
    /** Google-specific legacy type. */
    FILESET,

    /**
     * A symlink. Not chased, can be dangling. All we care about is the return value of {@code
     * readlink()}.
     */
    UNRESOLVED_SYMLINK,

    /** A subtree containing multiple files and directories. */
    TREE,

    /** Special artifact type for workspace status information. */
    CONSTANT_METADATA,
  }

  /**
   * A special kind of artifact that either is a fileset or needs special metadata caching behavior.
   *
   * <p>We subclass {@link DerivedArtifact} instead of storing the special attributes inside in
   * order to save memory. The proportion of artifacts that are special is very small, and by not
   * having to keep around the attribute for the rest we save some memory.
   */
  public static final class SpecialArtifact extends DerivedArtifact {
    private final SpecialArtifactType type;

    @VisibleForTesting
    public static SpecialArtifact create(
        ArtifactRoot root, PathFragment execPath, ActionLookupKey owner, SpecialArtifactType type) {
      return new SpecialArtifact(root, execPath, owner, type);
    }

    private SpecialArtifact(
        ArtifactRoot root, PathFragment execPath, Object owner, SpecialArtifactType type) {
      super(root, execPath, owner);
      this.type = type;
    }

    @Override
    public boolean isFileset() {
      return type == SpecialArtifactType.FILESET;
    }

    @Override
    public boolean isConstantMetadata() {
      return type == SpecialArtifactType.CONSTANT_METADATA;
    }

    @Override
    public boolean isTreeArtifact() {
      return type == SpecialArtifactType.TREE;
    }

    @Override
    public boolean isSymlink() {
      return type == SpecialArtifactType.UNRESOLVED_SYMLINK;
    }

    @Override
    public boolean hasParent() {
      return false;
    }

    @Override
    @Nullable
    public PathFragment getParentRelativePath() {
      return null;
    }

    @Override
    public ShareabilityOfValue getShareabilityOfValue() {
      return isConstantMetadata() ? ShareabilityOfValue.NEVER : super.getShareabilityOfValue();
    }
  }

  // Keep in sync with DerivedArtifactCodec.
  @SuppressWarnings("unused") // Used by reflection.
  private static final class SpecialArtifactCodec implements ObjectCodec<SpecialArtifact> {

    @Override
    public Class<SpecialArtifact> getEncodedClass() {
      return SpecialArtifact.class;
    }

    @Override
    public void serialize(
        SerializationContext context, SpecialArtifact obj, CodedOutputStream codedOut)
        throws SerializationException, IOException {
      context.serialize(obj.getRoot(), codedOut);
      context.serialize(obj.getRootRelativePath(), codedOut);
      context.serialize(getGeneratingActionKeyForSerialization(obj, context), codedOut);
      context.serialize(obj.type, codedOut);
    }

    @Override
    public SpecialArtifact deserialize(DeserializationContext context, CodedInputStream codedIn)
        throws SerializationException, IOException {
      ArtifactRoot root = context.deserialize(codedIn);
      PathFragment rootRelativePath = context.deserialize(codedIn);
      Object generatingActionKey = context.deserialize(codedIn);
      SpecialArtifactType type = context.deserialize(codedIn);
      SpecialArtifact artifact =
          new SpecialArtifact(
              root,
              getExecPathForDeserialization(root, rootRelativePath, generatingActionKey),
              generatingActionKey,
              type);
      return (SpecialArtifact)
          context.getDependency(ArtifactSerializationContext.class).intern(artifact);
    }
  }

  /**
   * Artifact representing a single-file archive with the filesystem tree belonging to a {@linkplain
   * SpecialArtifact tree artifact}.
   *
   * <p>The archive is equivalent to the entire tree artifact -- it contains all of the {@linkplain
   * TreeFileArtifact children} (and nothing else) of the tree artifact with their filesystem
   * structure, relative to the {@linkplain SpecialArtifact#getExecPath() tree artifact directory}.
   */
  public static final class ArchivedTreeArtifact extends DerivedArtifact {
    private static final PathFragment DEFAULT_DERIVED_TREE_ROOT =
        PathFragment.create(":archived_tree_artifacts");

    private final SpecialArtifact treeArtifact;

    private ArchivedTreeArtifact(
        SpecialArtifact treeArtifact,
        ArtifactRoot root,
        PathFragment execPath,
        Object generatingActionKey) {
      super(root, execPath, generatingActionKey);
      Preconditions.checkArgument(
          treeArtifact.isTreeArtifact(), "Not a tree artifact: %s", treeArtifact);
      this.treeArtifact = treeArtifact;
    }

    @Override
    public SpecialArtifact getParent() {
      return treeArtifact;
    }

    /**
     * Creates an {@link ArchivedTreeArtifact} for a given tree artifact at the path inferred from
     * the provided tree.
     *
     * <p>Returned artifact is stored in a permanent location, therefore can be shared across
     * actions and builds.
     *
     * <p>Example: for a tree artifact of {@code bazel-out/k8-fastbuild/bin/directory} returns an
     * {@linkplain ArchivedTreeArtifact artifact} of: {@code
     * bazel-out/:archived_tree_artifacts/k8-fastbuild/bin/directory.zip}.
     */
    public static ArchivedTreeArtifact createForTree(SpecialArtifact treeArtifact) {
      return createInternal(
          treeArtifact,
          DEFAULT_DERIVED_TREE_ROOT,
          treeArtifact.getRootRelativePath().replaceName(treeArtifact.getFilename() + ".zip"),
          treeArtifact.getGeneratingActionKey());
    }

    /**
     * Creates an {@link ArchivedTreeArtifact} for a given tree artifact within provided derived
     * tree directory.
     *
     * <p>Example: for a tree artifact with root of {@code bazel-out/k8-fastbuild/bin} returns an
     * {@linkplain ArchivedTreeArtifact artifact} of: {@code
     * bazel-out/{derivedTreeRoot}/k8-fastbuild/bin/{rootRelativePath}} with root of: {@code
     * bazel-out/{derivedTreeRoot}/k8-fastbuild/bin}.
     *
     * <p>Such artifacts should only be used as outputs of intermediate spawns. Action execution
     * results must come from {@link #createForTree}.
     */
    public static ArchivedTreeArtifact createWithCustomDerivedTreeRoot(
        SpecialArtifact treeArtifact, PathFragment derivedTreeRoot, PathFragment rootRelativePath) {
      return createInternal(
          treeArtifact, derivedTreeRoot, rootRelativePath, treeArtifact.getGeneratingActionKey());
    }

    private static ArchivedTreeArtifact createInternal(
        SpecialArtifact treeArtifact,
        PathFragment derivedTreeRoot,
        PathFragment rootRelativePath,
        Object generatingActionKey) {
      ArtifactRoot treeRoot = treeArtifact.getRoot();
      PathFragment archiveRoot = embedDerivedTreeRoot(treeRoot.getExecPath(), derivedTreeRoot);
      return new ArchivedTreeArtifact(
          treeArtifact,
          ArtifactRoot.asDerivedRoot(getExecRoot(treeRoot), RootType.Output, archiveRoot),
          archiveRoot.getRelative(rootRelativePath),
          generatingActionKey);
    }

    /**
     * Returns an exec path within the archived artifacts directory tree corresponding to the
     * provided one.
     *
     * <p>Example: {@code bazel-out/k8-fastbuild/bin ->
     * bazel-out/{customDerivedTreeRoot}/k8-fastbuild/bin}.
     */
    public static PathFragment getExecPathWithinArchivedArtifactsTree(PathFragment execPath) {
      return embedDerivedTreeRoot(execPath, DEFAULT_DERIVED_TREE_ROOT);
    }

    /**
     * Translates provided output {@code execPath} to one under provided derived tree root.
     *
     * <p>Example: {@code bazel-out/k8-fastbuild/bin ->
     * bazel-out/{derivedTreeRoot}/k8-fastbuild/bin}.
     */
    private static PathFragment embedDerivedTreeRoot(
        PathFragment execPath, PathFragment derivedTreeRoot) {
      return execPath
          .subFragment(0, 1)
          .getRelative(derivedTreeRoot)
          .getRelative(execPath.subFragment(1));
    }

    private static Path getExecRoot(ArtifactRoot artifactRoot) {
      // /output_base/execroot/bazel-out/k8-fastbuild/bin
      Path rootPath = artifactRoot.getRoot().asPath();
      PathFragment rootPathFragment = rootPath.asFragment();
      // /output_base/execroot
      PathFragment execRootPath =
          rootPathFragment.subFragment(
              0, rootPathFragment.segmentCount() - artifactRoot.getExecPath().segmentCount());
      return rootPath.getFileSystem().getPath(execRootPath);
    }
  }

  @SuppressWarnings("unused") // Codec used by reflection.
  private static final class ArchivedTreeArtifactCodec
      implements ObjectCodec<ArchivedTreeArtifact> {

    @Override
    public Class<ArchivedTreeArtifact> getEncodedClass() {
      return ArchivedTreeArtifact.class;
    }

    @Override
    public void serialize(
        SerializationContext context, ArchivedTreeArtifact obj, CodedOutputStream codedOut)
        throws SerializationException, IOException {
      PathFragment derivedTreeRoot = obj.getRoot().getExecPath().subFragment(1, 2);

      context.serialize(obj.getParent(), codedOut);
      context.serialize(derivedTreeRoot, codedOut);
      context.serialize(obj.getRootRelativePath(), codedOut);
    }

    @Override
    public ArchivedTreeArtifact deserialize(
        DeserializationContext context, CodedInputStream codedIn)
        throws SerializationException, IOException {
      SpecialArtifact treeArtifact = context.deserialize(codedIn);
      PathFragment derivedTreeRoot = context.deserialize(codedIn);
      PathFragment rootRelativePath = context.deserialize(codedIn);
      Object generatingActionKey =
          treeArtifact.hasGeneratingActionKey()
              ? treeArtifact.getGeneratingActionKey()
              : OMITTED_FOR_SERIALIZATION;

      return ArchivedTreeArtifact.createInternal(
          treeArtifact, derivedTreeRoot, rootRelativePath, generatingActionKey);
    }
  }

  /**
   * A special kind of artifact that represents a concrete file created at execution time under its
   * associated parent TreeArtifact.
   *
   * <p>TreeFileArtifacts should be only created during execution time inside some special actions
   * to support action inputs and outputs that are unpredictable at analysis time. TreeFileArtifacts
   * should not be created directly by any rules at analysis time.
   *
   * <p>There are two types of TreeFileArtifacts:
   *
   * <ol>
   *   <li>Outputs under a directory created by an action using {@code declare_directory}. In this
   *       case, a single action creates both the parent and all of the children. Instances should
   *       be created by calling {@link #createTreeOutput}. {@link #isChildOfDeclaredDirectory} will
   *       return {@code true}.
   *   <li>Outputs of an action template expansion. In this case, the parent directory is not
   *       actually produced by any action, but rather serves as a placeholder for dependant actions
   *       to declare a dep on during analysis, before the children are known. The children are
   *       created by various actions (from the template expansion). Instances should be created by
   *       calling {@link #createTemplateExpansionOutput}. {@link #isChildOfDeclaredDirectory} will
   *       return {@code false}.
   * </ol>
   */
  public static final class TreeFileArtifact extends DerivedArtifact {
    private final SpecialArtifact parent;
    private final PathFragment parentRelativePath;

    /**
     * Creates a {@link TreeFileArtifact} representing a child of the given parent tree artifact.
     *
     * <p>The child should already have been created by the parent's generating action. For this
     * reason, {@link DerivedArtifact#hasGeneratingActionKey} on the parent must be {@code true}
     * when this is called. The child is set with the same generating action.
     */
    public static TreeFileArtifact createTreeOutput(
        SpecialArtifact parent, PathFragment parentRelativePath) {
      Preconditions.checkArgument(
          parent.hasGeneratingActionKey(),
          "%s has no generating action key (parent owner: %s, parent relative path: %s)",
          parent,
          parent.getArtifactOwner(),
          parentRelativePath);
      ActionLookupData generatingActionKey = parent.getGeneratingActionKey();
      Preconditions.checkArgument(
          !isActionTemplateExpansionKey(generatingActionKey.getActionLookupKey()),
          "%s owned by action template expansion %s (parent relative path: %s)",
          parent,
          generatingActionKey.getActionLookupKey(),
          parentRelativePath);
      return new TreeFileArtifact(parent, parentRelativePath, generatingActionKey);
    }

    /**
     * Convenience method for {@link #createTreeOutput(SpecialArtifact, PathFragment)} with a string
     * relative path.
     */
    public static TreeFileArtifact createTreeOutput(
        SpecialArtifact parent, String parentRelativePath) {
      return createTreeOutput(parent, PathFragment.create(parentRelativePath));
    }

    /**
     * Creates a {@link TreeFileArtifact} representing the output of an action generated dynamically
     * by an {@link ActionTemplate} during the execution phase.
     *
     * <p>The returned artifact does not yet have a generating action set.
     */
    public static TreeFileArtifact createTemplateExpansionOutput(
        SpecialArtifact parent, PathFragment parentRelativePath, ActionLookupKey owner) {
      Preconditions.checkArgument(
          isActionTemplateExpansionKey(owner),
          "Template expansion outputs must be owned by an action template expansion key, but %s is"
              + " owned by %s (parent relative path: %s)",
          parent,
          owner,
          parentRelativePath);
      return new TreeFileArtifact(parent, parentRelativePath, owner);
    }

    /**
     * Convenience method for {@link #createTemplateExpansionOutput(SpecialArtifact, PathFragment,
     * ActionLookupKey)} with a string relative path.
     */
    public static TreeFileArtifact createTemplateExpansionOutput(
        SpecialArtifact parent, String parentRelativePath, ActionLookupKey owner) {
      return createTemplateExpansionOutput(parent, PathFragment.create(parentRelativePath), owner);
    }

    private TreeFileArtifact(
        SpecialArtifact parent, PathFragment parentRelativePath, Object owner) {
      super(parent.getRoot(), parent.getExecPath().getRelative(parentRelativePath), owner);
      Preconditions.checkArgument(
          parent.isTreeArtifact(),
          "The parent of TreeFileArtifact (parent-relative path: %s) is not a TreeArtifact: %s",
          parentRelativePath,
          parent);
      Preconditions.checkArgument(
          !parentRelativePath.containsUplevelReferences() && !parentRelativePath.isAbsolute(),
          "%s is not a proper normalized relative path",
          parentRelativePath);
      this.parent = parent;
      this.parentRelativePath = parentRelativePath;
    }

    @Override
    public SpecialArtifact getParent() {
      return parent;
    }

    @Override
    public PathFragment getParentRelativePath() {
      return parentRelativePath;
    }

    @Override
    public String getTreeRelativePathString() {
      return parentRelativePath.getPathString();
    }

    @Override
    public boolean isChildOfDeclaredDirectory() {
      return !isActionTemplateExpansionKey(getArtifactOwner());
    }

    private static boolean isActionTemplateExpansionKey(ActionLookupKey key) {
      return SkyFunctions.ACTION_TEMPLATE_EXPANSION.equals(key.functionName());
    }
  }

  @SuppressWarnings("unused") // Used by reflection.
  private static final class TreeFileArtifactCodec implements ObjectCodec<TreeFileArtifact> {

    @Override
    public Class<TreeFileArtifact> getEncodedClass() {
      return TreeFileArtifact.class;
    }

    @Override
    public void serialize(
        SerializationContext context, TreeFileArtifact obj, CodedOutputStream codedOut)
        throws SerializationException, IOException {
      context.serialize(obj.parent, codedOut);
      context.serialize(obj.parentRelativePath, codedOut);
      context.serialize(getGeneratingActionKeyForSerialization(obj, context), codedOut);
    }

    @Override
    public TreeFileArtifact deserialize(DeserializationContext context, CodedInputStream codedIn)
        throws SerializationException, IOException {
      SpecialArtifact parent = context.deserialize(codedIn);
      PathFragment parentRelativePath = context.deserialize(codedIn);
      Object generatingActionKey = context.deserialize(codedIn);
      return new TreeFileArtifact(parent, parentRelativePath, generatingActionKey);
    }
  }

  // ---------------------------------------------------------------------------
  // Static methods to assist in working with Artifacts

  /** Formatter for execPath PathFragment output. */
  public static final Function<Artifact, String> ROOT_RELATIVE_PATH_STRING =
      artifact -> artifact.getRootRelativePath().getPathString();

  public static final Function<Artifact, String> RUNFILES_PATH_STRING =
      artifact -> artifact.getRunfilesPath().getPathString();

  /**
   * Converts a collection of artifacts into execution-time path strings, and
   * adds those to a given collection. Middleman artifacts are ignored by this
   * method.
   */
  public static void addExecPaths(Iterable<Artifact> artifacts, Collection<String> output) {
    addNonMiddlemanArtifacts(artifacts, output, ActionInput::getExecPathString);
  }

  /**
   * Converts a collection of artifacts into the outputs computed by outputFormatter and adds them
   * to a given collection. Middleman artifacts are ignored.
   */
  public static <E> void addNonMiddlemanArtifacts(
      Iterable<Artifact> artifacts,
      Collection<? super E> output,
      Function<? super Artifact, E> outputFormatter) {
    for (Artifact artifact : artifacts) {
      if (MIDDLEMAN_FILTER.apply(artifact)) {
        output.add(outputFormatter.apply(artifact));
      }
    }
  }

  /**
   * Lazily converts artifacts into root-relative path strings. Middleman artifacts are ignored by
   * this method.
   */
  public static Iterable<String> toRootRelativePaths(NestedSet<Artifact> artifacts) {
    return toRootRelativePaths(artifacts.toList());
  }

  /**
   * Lazily converts artifacts into root-relative path strings. Middleman artifacts are ignored by
   * this method.
   */
  public static Iterable<String> toRootRelativePaths(Iterable<Artifact> artifacts) {
    return Iterables.transform(
        Iterables.filter(artifacts, MIDDLEMAN_FILTER),
        artifact -> artifact.getRootRelativePath().getPathString());
  }

  /**
   * Lazily converts artifacts into execution-time path strings. Middleman artifacts are ignored by
   * this method.
   */
  public static Iterable<String> toExecPaths(Iterable<Artifact> artifacts) {
    return Iterables.transform(
        Iterables.filter(artifacts, MIDDLEMAN_FILTER), ActionInput::getExecPathString);
  }

  /**
   * Converts a collection of artifacts into execution-time path strings, and returns those as an
   * immutable list. Middleman artifacts are ignored by this method.
   *
   * <p>Avoid this method in production code - it flattens the given nested set unconditionally.
   */
  @VisibleForTesting
  public static List<String> asExecPaths(NestedSet<Artifact> artifacts) {
    return asExecPaths(artifacts.toList());
  }

  /**
   * Converts a collection of artifacts into execution-time path strings, and
   * returns those as an immutable list. Middleman artifacts are ignored by this method.
   */
  public static List<String> asExecPaths(Iterable<Artifact> artifacts) {
    return ImmutableList.copyOf(toExecPaths(artifacts));
  }

  /**
   * Renders a collection of artifacts as execution-time paths and joins
   * them into a single string. Middleman artifacts are ignored by this method.
   */
  public static String joinExecPaths(String delimiter, Iterable<Artifact> artifacts) {
    return Joiner.on(delimiter).join(toExecPaths(artifacts));
  }

  /**
   * Renders a collection of artifacts as root-relative paths and joins
   * them into a single string. Middleman artifacts are ignored by this method.
   */
  public static String joinRootRelativePaths(String delimiter, Iterable<Artifact> artifacts) {
    return Joiner.on(delimiter).join(toRootRelativePaths(artifacts));
  }

  /** Adds a collection of artifacts to a given collection, with middleman actions expanded once. */
  static void addExpandedArtifacts(
      Iterable<Artifact> artifacts,
      Collection<? super Artifact> output,
      ArtifactExpander artifactExpander) {
    addExpandedArtifacts(artifacts, output, Functions.identity(), artifactExpander);
  }

  /**
   * Converts a collection of artifacts into the outputs computed by
   * outputFormatter and adds them to a given collection. Middleman artifacts
   * are expanded once.
   */
  private static <E> void addExpandedArtifacts(Iterable<? extends Artifact> artifacts,
                                               Collection<? super E> output,
                                               Function<? super Artifact, E> outputFormatter,
                                               ArtifactExpander artifactExpander) {
    for (Artifact artifact : artifacts) {
      if (artifact.isMiddlemanArtifact() || artifact.isTreeArtifact()) {
        expandArtifact(artifact, output, outputFormatter, artifactExpander);
      } else {
        output.add(outputFormatter.apply(artifact));
      }
    }
  }

  private static <E> void expandArtifact(Artifact middleman,
      Collection<? super E> output,
      Function<? super Artifact, E> outputFormatter,
      ArtifactExpander artifactExpander) {
    Preconditions.checkArgument(middleman.isMiddlemanArtifact() || middleman.isTreeArtifact());
    List<Artifact> artifacts = new ArrayList<>();
    artifactExpander.expand(middleman, artifacts);
    for (Artifact artifact : artifacts) {
      output.add(outputFormatter.apply(artifact));
    }
  }

  /**
   * Convenience method to filter the files to build for a certain filetype.
   *
   * @param artifacts the files to filter
   * @param allowedType the allowed filetype
   * @return all members of filesToBuild that are of one of the
   *     allowed filetypes
   */
  public static List<Artifact> filterFiles(Iterable<Artifact> artifacts, FileType allowedType) {
    List<Artifact> filesToBuild = new ArrayList<>();
    for (Artifact artifact : artifacts) {
      if (allowedType.apply(artifact.getFilename())) {
        filesToBuild.add(artifact);
      }
    }
    return filesToBuild;
  }

  /**
   * Converts artifacts into their exec paths. Returns an immutable list.
   */
  public static List<PathFragment> asPathFragments(Iterable<? extends Artifact> artifacts) {
    return Streams.stream(artifacts).map(Artifact::getExecPath).collect(toImmutableList());
  }

  /**
   * Returns the exec paths of the input artifacts in alphabetical order.
   */
  public static ImmutableList<PathFragment> asSortedPathFragments(Iterable<Artifact> input) {
    return Streams.stream(input).map(Artifact::getExecPath).sorted().collect(toImmutableList());
  }


  @Override
  public boolean isImmutable() {
    return true;
  }

  @Override
  public void repr(Printer printer) {
    if (isSourceArtifact()) {
      printer.append("<source file " + getRootRelativePathString() + ">");
    } else {
      printer.append("<generated file " + getRootRelativePathString() + ">");
    }
  }

  /**
   * A utility class that compares {@link Artifact}s without taking their owners into account.
   * Should only be used for detecting action conflicts and merging shared action data.
   */
  public static final class OwnerlessArtifactWrapper {
    private final Artifact artifact;

    public OwnerlessArtifactWrapper(Artifact artifact) {
      this.artifact = artifact;
    }

    @Override
    public int hashCode() {
      // Depends on the fact that Artifact#hashCode does not use ArtifactOwner.
      return artifact.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
      return obj instanceof OwnerlessArtifactWrapper
          && this.artifact.equalsWithoutOwner(((OwnerlessArtifactWrapper) obj).artifact);
    }

    @Override
    public String toString() {
      return MoreObjects.toStringHelper(this).add("artifact", artifact.toDebugString()).toString();
    }
  }
}
