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

import com.google.common.base.Preconditions;
import com.google.common.hash.Hasher;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrintable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import com.google.devtools.build.lib.util.FileType;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;

/**
 * A local file path representing a file on the host machine. You should use this when you want to
 * access local files via the file system.
 *
 * <p>Paths are always absolute.
 *
 * <p>Strings are normalized with '.' and '..' removed and resolved (if possible), any multiple
 * slashes ('/') removed, and any trailing slash also removed. Windows drive letters are uppercased.
 * The current implementation does not touch the incoming path string unless the string actually
 * needs to be normalized.
 *
 * <p>There is some limited support for Windows-style paths. Most importantly, drive identifiers in
 * front of a path (c:/abc) are supported and such paths are correctly recognized as absolute, as
 * are paths with backslash separators (C:\\foo\\bar). However, advanced Windows-style features like
 * \\\\network\\paths and \\\\?\\unc\\paths are not supported. We are currently using forward
 * slashes ('/') even on Windows, so backslashes '\' get converted to forward slashes during
 * normalization.
 *
 * <p>Mac and Windows file paths are case insensitive. Case is preserved.
 */
@ThreadSafe
@AutoCodec
public class Path
    implements Comparable<Path>, Serializable, SkylarkPrintable, FileType.HasFileType {
  private static FileSystem fileSystemForSerialization;

  /**
   * We need to specify used FileSystem. In this case we can save memory during the serialization.
   */
  public static void setFileSystemForSerialization(FileSystem fileSystem) {
    fileSystemForSerialization = fileSystem;
  }

  /**
   * Returns FileSystem that we are using.
   */
  public static FileSystem getFileSystemForSerialization() {
    return fileSystemForSerialization;
  }

  private static final OsPathPolicy OS = OsPathPolicy.getFilePathOs();
  private static final char SEPARATOR = OS.getSeparator();

  private String path;
  private int driveStrLength; // 1 on Unix, 3 on Windows
  private FileSystem fileSystem;

  /** Creates a local path that is specific to the host OS. */
  static Path create(String path, FileSystem fileSystem) {
    Preconditions.checkNotNull(path);
    int normalizationLevel = OS.needsToNormalize(path);
    String normalizedPath = OS.normalize(path, normalizationLevel);
    return createAlreadyNormalized(normalizedPath, fileSystem);
  }

  @AutoCodec.VisibleForSerialization
  @AutoCodec.Instantiator
  static Path createAlreadyNormalized(String path, FileSystem fileSystem) {
    int driveStrLength = OS.getDriveStrLength(path);
    return createAlreadyNormalized(path, driveStrLength, fileSystem);
  }

  static Path createAlreadyNormalized(String path, int driveStrLength, FileSystem fileSystem) {
    return new Path(path, driveStrLength, fileSystem);
  }

  /** This method expects path to already be normalized. */
  private Path(String path, int driveStrLength, FileSystem fileSystem) {
    Preconditions.checkArgument(driveStrLength > 0, "Paths must be absolute: '%s'", path);
    this.path = Preconditions.checkNotNull(path);
    this.driveStrLength = driveStrLength;
    this.fileSystem = fileSystem;
  }

  public String getPathString() {
    return path;
  }

  @Override
  public String filePathForFileTypeMatcher() {
    return path;
  }

  /**
   * Returns the name of the leaf file or directory.
   *
   * <p>If called on a {@link Path} instance for a mount name (eg. '/' or 'C:/'), the empty string
   * is returned.
   */
  public String getBaseName() {
    int lastSeparator = path.lastIndexOf(SEPARATOR);
    return lastSeparator < driveStrLength
        ? path.substring(driveStrLength)
        : path.substring(lastSeparator + 1);
  }

  /** Synonymous with {@link Path#getRelative(String)}. */
  public Path getChild(String child) {
    FileSystemUtils.checkBaseName(child);
    return getRelative(child);
  }

  /**
   * Returns a {@link Path} instance representing the relative path between this {@link Path} and
   * the given path.
   */
  public Path getRelative(PathFragment other) {
    Preconditions.checkNotNull(other);
    String otherStr = other.getPathString();
    // Fast-path: The path fragment is already normal, use cheaper normalization check
    return getRelative(otherStr, other.getDriveStrLength(), OS.needsToNormalizeSuffix(otherStr));
  }

  /**
   * Returns a {@link Path} instance representing the relative path between this {@link Path} and
   * the given path.
   */
  public Path getRelative(String other) {
    Preconditions.checkNotNull(other);
    return getRelative(other, OS.getDriveStrLength(other), OS.needsToNormalize(other));
  }

  private Path getRelative(String other, int otherDriveStrLength, int normalizationLevel) {
    if (other.isEmpty()) {
      return this;
    }
    // This is an absolute path, simply return it
    if (otherDriveStrLength > 0) {
      String normalizedPath = OS.normalize(other, normalizationLevel);
      return new Path(normalizedPath, otherDriveStrLength, fileSystem);
    }
    String newPath;
    if (path.length() == driveStrLength) {
      newPath = path + other;
    } else {
      newPath = path + '/' + other;
    }
    // Note that even if other came from a PathFragment instance we still might
    // need to normalize the result if (for instance) other is a path that
    // starts with '..'
    newPath = OS.normalize(newPath, normalizationLevel);
    return new Path(newPath, driveStrLength, fileSystem);
  }

  /**
   * Returns the parent directory of this {@link Path}.
   *
   * <p>If called on a root (like '/'), it returns null.
   */
  @Nullable
  public Path getParentDirectory() {
    int lastSeparator = path.lastIndexOf(SEPARATOR);
    if (lastSeparator < driveStrLength) {
      if (path.length() > driveStrLength) {
        String newPath = path.substring(0, driveStrLength);
        return new Path(newPath, driveStrLength, fileSystem);
      } else {
        return null;
      }
    }
    String newPath = path.substring(0, lastSeparator);
    return new Path(newPath, driveStrLength, fileSystem);
  }

  /**
   * Returns the drive.
   *
   * <p>On unix, this will return "/". On Windows it will return the drive letter, like "C:/".
   */
  public String getDriveStr() {
    return path.substring(0, driveStrLength);
  }

  /**
   * Returns the {@link Path} relative to the base {@link Path}.
   *
   * <p>For example, <code>Path.create("foo/bar/wiz").relativeTo(Path.create("foo"))
   * </code> returns <code>Path.create("bar/wiz")</code>.
   *
   * <p>If the {@link Path} is not a child of the passed {@link Path} an {@link
   * IllegalArgumentException} is thrown. In particular, this will happen whenever the two {@link
   * Path} instances aren't both absolute or both relative.
   */
  public PathFragment relativeTo(Path base) {
    Preconditions.checkNotNull(base);
    checkSameFileSystem(base);
    String basePath = base.path;
    if (!OS.startsWith(path, basePath)) {
      throw new IllegalArgumentException(
          String.format("Path '%s' is not under '%s', cannot relativize", this, base));
    }
    int bn = basePath.length();
    if (bn == 0) {
      return PathFragment.createAlreadyNormalized(path, driveStrLength);
    }
    if (path.length() == bn) {
      return PathFragment.EMPTY_FRAGMENT;
    }
    final int lastSlashIndex;
    if (basePath.charAt(bn - 1) == '/') {
      lastSlashIndex = bn - 1;
    } else {
      lastSlashIndex = bn;
    }
    if (path.charAt(lastSlashIndex) != '/') {
      throw new IllegalArgumentException(
          String.format("Path '%s' is not under '%s', cannot relativize", this, base));
    }
    String newPath = path.substring(lastSlashIndex + 1);
    return PathFragment.createAlreadyNormalized(newPath, 0);
  }

  /**
   * Returns whether this path is an ancestor of another path.
   *
   * <p>A path is considered an ancestor of itself.
   */
  public boolean startsWith(Path other) {
    if (fileSystem != other.fileSystem) {
      return false;
    }
    return startsWith(other.path, other.driveStrLength);
  }

  /**
   * Returns whether this path is an ancestor of another path.
   *
   * <p>A path is considered an ancestor of itself.
   *
   * <p>An absolute path can never be an ancestor of a relative path fragment.
   */
  public boolean startsWith(PathFragment other) {
    if (!other.isAbsolute()) {
      return false;
    }
    String otherPath = other.getPathString();
    return startsWith(otherPath, OS.getDriveStrLength(otherPath));
  }

  private boolean startsWith(String otherPath, int otherDriveStrLength) {
    Preconditions.checkNotNull(otherPath);
    if (otherPath.length() > path.length()) {
      return false;
    }
    if (driveStrLength != otherDriveStrLength) {
      return false;
    }
    if (!OS.startsWith(path, otherPath)) {
      return false;
    }
    return path.length() == otherPath.length() // Handle equal paths
        || otherPath.length() == driveStrLength // Handle (eg.) 'C:/foo' starts with 'C:/'
        // Handle 'true' ancestors, eg. "foo/bar" starts with "foo", but does not start with "fo"
        || path.charAt(otherPath.length()) == SEPARATOR;
  }

  public FileSystem getFileSystem() {
    return fileSystem;
  }

  public PathFragment asFragment() {
    return PathFragment.createAlreadyNormalized(path, driveStrLength);
  }

  @Override
  public String toString() {
    return path;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    Path other = (Path) o;
    if (fileSystem != other.fileSystem) {
      return false;
    }
    return OS.equals(this.path, other.path);
  }

  @Override
  public int hashCode() {
    // Do not include file system for efficiency.
    // In practice we never construct paths from different file systems.
    return OS.hash(this.path);
  }

  @Override
  public int compareTo(Path o) {
    // If they are on different file systems, the file system decides the ordering.
    FileSystem otherFs = o.getFileSystem();
    if (!fileSystem.equals(otherFs)) {
      int thisFileSystemHash = System.identityHashCode(fileSystem);
      int otherFileSystemHash = System.identityHashCode(otherFs);
      if (thisFileSystemHash < otherFileSystemHash) {
        return -1;
      } else if (thisFileSystemHash > otherFileSystemHash) {
        return 1;
      }
    }
    return OS.compare(this.path, o.path);
  }

  @Override
  public void repr(SkylarkPrinter printer) {
    printer.append(path);
  }

  @Override
  public void str(SkylarkPrinter printer) {
    repr(printer);
  }

  /** Returns true iff this path denotes an existing file of any kind. Follows symbolic links. */
  public boolean exists() {
    return fileSystem.exists(this, true);
  }

  /**
   * Returns true iff this path denotes an existing file of any kind.
   *
   * @param followSymlinks if {@link Symlinks#FOLLOW}, and this path denotes a symbolic link, the
   *     link is dereferenced until a file other than a symbolic link is found
   */
  public boolean exists(Symlinks followSymlinks) {
    return fileSystem.exists(this, followSymlinks.toBoolean());
  }

  /**
   * Returns a new, immutable collection containing the names of all entities within the directory
   * denoted by the current path. Follows symbolic links.
   *
   * @throws FileNotFoundException If the directory is not found
   * @throws IOException If the path does not denote a directory
   */
  public Collection<Path> getDirectoryEntries() throws IOException, FileNotFoundException {
    Collection<String> entries = fileSystem.getDirectoryEntries(this);
    Collection<Path> result = new ArrayList<>(entries.size());
    for (String entry : entries) {
      result.add(getChild(entry));
    }
    return result;
  }

  /**
   * Returns a collection of the names and types of all entries within the directory denoted by the
   * current path. Follows symbolic links if {@code followSymlinks} is true. Note that the order of
   * the returned entries is not guaranteed.
   *
   * @param followSymlinks whether to follow symlinks or not
   * @throws FileNotFoundException If the directory is not found
   * @throws IOException If the path does not denote a directory
   */
  public Collection<Dirent> readdir(Symlinks followSymlinks) throws IOException {
    return fileSystem.readdir(this, followSymlinks.toBoolean());
  }

  /**
   * Returns the status of a file, following symbolic links.
   *
   * @throws IOException if there was an error obtaining the file status. Note, some implementations
   *     may defer the I/O, and hence the throwing of the exception, until the accessor methods of
   *     {@code FileStatus} are called.
   */
  public FileStatus stat() throws IOException {
    return fileSystem.stat(this, true);
  }

  /** Like stat(), but returns null on file-nonexistence instead of throwing. */
  public FileStatus statNullable() {
    return statNullable(Symlinks.FOLLOW);
  }

  /** Like stat(), but returns null on file-nonexistence instead of throwing. */
  public FileStatus statNullable(Symlinks symlinks) {
    return fileSystem.statNullable(this, symlinks.toBoolean());
  }

  /**
   * Returns the status of a file, optionally following symbolic links.
   *
   * @param followSymlinks if {@link Symlinks#FOLLOW}, and this path denotes a symbolic link, the
   *     link is dereferenced until a file other than a symbolic link is found
   * @throws IOException if there was an error obtaining the file status. Note, some implementations
   *     may defer the I/O, and hence the throwing of the exception, until the accessor methods of
   *     {@code FileStatus} are called
   */
  public FileStatus stat(Symlinks followSymlinks) throws IOException {
    return fileSystem.stat(this, followSymlinks.toBoolean());
  }

  /**
   * Like {@link #stat}, but may return null if the file is not found (corresponding to {@code
   * ENOENT} and {@code ENOTDIR} in Unix's stat(2) function) instead of throwing. Follows symbolic
   * links.
   */
  public FileStatus statIfFound() throws IOException {
    return fileSystem.statIfFound(this, true);
  }

  /**
   * Like {@link #stat}, but may return null if the file is not found (corresponding to {@code
   * ENOENT} and {@code ENOTDIR} in Unix's stat(2) function) instead of throwing.
   *
   * @param followSymlinks if {@link Symlinks#FOLLOW}, and this path denotes a symbolic link, the
   *     link is dereferenced until a file other than a symbolic link is found
   */
  public FileStatus statIfFound(Symlinks followSymlinks) throws IOException {
    return fileSystem.statIfFound(this, followSymlinks.toBoolean());
  }

  /** Returns true iff this path denotes an existing directory. Follows symbolic links. */
  public boolean isDirectory() {
    return fileSystem.isDirectory(this, true);
  }

  /**
   * Returns true iff this path denotes an existing directory.
   *
   * @param followSymlinks if {@link Symlinks#FOLLOW}, and this path denotes a symbolic link, the
   *     link is dereferenced until a file other than a symbolic link is found
   */
  public boolean isDirectory(Symlinks followSymlinks) {
    return fileSystem.isDirectory(this, followSymlinks.toBoolean());
  }

  /**
   * Returns true iff this path denotes an existing regular or special file. Follows symbolic links.
   *
   * <p>For our purposes, "file" includes special files (socket, fifo, block or char devices) too;
   * it excludes symbolic links and directories.
   */
  public boolean isFile() {
    return fileSystem.isFile(this, true);
  }

  /**
   * Returns true iff this path denotes an existing regular or special file.
   *
   * <p>For our purposes, a "file" includes special files (socket, fifo, block or char devices) too;
   * it excludes symbolic links and directories.
   *
   * @param followSymlinks if {@link Symlinks#FOLLOW}, and this path denotes a symbolic link, the
   *     link is dereferenced until a file other than a symbolic link is found.
   */
  public boolean isFile(Symlinks followSymlinks) {
    return fileSystem.isFile(this, followSymlinks.toBoolean());
  }

  /**
   * Returns true iff this path denotes an existing special file (e.g. fifo). Follows symbolic
   * links.
   */
  public boolean isSpecialFile() {
    return fileSystem.isSpecialFile(this, true);
  }

  /**
   * Returns true iff this path denotes an existing special file (e.g. fifo).
   *
   * @param followSymlinks if {@link Symlinks#FOLLOW}, and this path denotes a symbolic link, the
   *     link is dereferenced until a path other than a symbolic link is found.
   */
  public boolean isSpecialFile(Symlinks followSymlinks) {
    return fileSystem.isSpecialFile(this, followSymlinks.toBoolean());
  }

  /**
   * Returns true iff this path denotes an existing symbolic link. Does not follow symbolic links.
   */
  public boolean isSymbolicLink() {
    return fileSystem.isSymbolicLink(this);
  }

  /**
   * Returns an output stream to the file denoted by the current path, creating it and truncating it
   * if necessary. The stream is opened for writing.
   *
   * @throws FileNotFoundException If the file cannot be found or created.
   * @throws IOException If a different error occurs.
   */
  public OutputStream getOutputStream() throws IOException, FileNotFoundException {
    return getOutputStream(false);
  }

  /**
   * Returns an output stream to the file denoted by the current path, creating it and truncating it
   * if necessary. The stream is opened for writing.
   *
   * @param append whether to open the file in append mode.
   * @throws FileNotFoundException If the file cannot be found or created.
   * @throws IOException If a different error occurs.
   */
  public OutputStream getOutputStream(boolean append) throws IOException, FileNotFoundException {
    return fileSystem.getOutputStream(this, append);
  }

  /**
   * Creates a directory with the name of the current path, not following symbolic links. Returns
   * normally iff the directory exists after the call: true if the directory was created by this
   * call, false if the directory was already in existence. Throws an exception if the directory
   * could not be created for any reason.
   *
   * @throws IOException if the directory creation failed for any reason
   */
  public boolean createDirectory() throws IOException {
    return fileSystem.createDirectory(this);
  }

  /**
   * Ensures that the directory with the name of the current path and all its ancestor directories
   * exist.
   *
   * <p>Does not return whether the directory already existed or was created by some other
   * concurrent call to this method.
   *
   * @throws IOException if the directory creation failed for any reason
   */
  public void createDirectoryAndParents() throws IOException {
    fileSystem.createDirectoryAndParents(this);
  }

  /**
   * Creates a symbolic link with the name of the current path, following symbolic links. The
   * referent of the created symlink is is the absolute path "target"; it is not possible to create
   * relative symbolic links via this method.
   *
   * @throws IOException if the creation of the symbolic link was unsuccessful for any reason
   */
  public void createSymbolicLink(Path target) throws IOException {
    checkSameFileSystem(target);
    fileSystem.createSymbolicLink(this, target.asFragment());
  }

  /**
   * Creates a symbolic link with the name of the current path, following symbolic links. The
   * referent of the created symlink is is the path fragment "target", which may be absolute or
   * relative.
   *
   * @throws IOException if the creation of the symbolic link was unsuccessful for any reason
   */
  public void createSymbolicLink(PathFragment target) throws IOException {
    fileSystem.createSymbolicLink(this, target);
  }

  /**
   * Returns the target of the current path, which must be a symbolic link. The link contents are
   * returned exactly, and may contain an absolute or relative path. Analogous to readlink(2).
   *
   * <p>Note: for {@link FileSystem}s where {@link FileSystem#supportsSymbolicLinksNatively(Path)}
   * returns false, this method will throw an {@link UnsupportedOperationException} if the link
   * points to a non-existent file.
   *
   * @return the content (i.e. target) of the symbolic link
   * @throws IOException if the current path is not a symbolic link, or the contents of the link
   *     could not be read for any reason
   */
  public PathFragment readSymbolicLink() throws IOException {
    return fileSystem.readSymbolicLink(this);
  }

  /**
   * If the current path is a symbolic link, returns the target of this symbolic link. The semantics
   * are intentionally left underspecified otherwise to permit efficient implementations.
   *
   * @return the content (i.e. target) of the symbolic link
   * @throws IOException if the current path is not a symbolic link, or the contents of the link
   *     could not be read for any reason
   */
  public PathFragment readSymbolicLinkUnchecked() throws IOException {
    return fileSystem.readSymbolicLinkUnchecked(this);
  }

  /**
   * Create a hard link for the current path.
   *
   * @param link the path of the new link
   * @throws IOException if there was an error executing {@link FileSystem#createHardLink}
   */
  public void createHardLink(Path link) throws IOException {
    fileSystem.createHardLink(link, this);
  }

  /**
   * Returns the canonical path for this path, by repeatedly replacing symbolic links with their
   * referents. Analogous to realpath(3).
   *
   * @return the canonical path for this path
   * @throws IOException if any symbolic link could not be resolved, or other error occurred (for
   *     example, the path does not exist)
   */
  public Path resolveSymbolicLinks() throws IOException {
    return fileSystem.resolveSymbolicLinks(this);
  }

  /**
   * Renames the file denoted by the current path to the location "target", not following symbolic
   * links.
   *
   * <p>Files cannot be atomically renamed across devices; copying is required. Use {@link
   * FileSystemUtils#copyFile} followed by {@link Path#delete}.
   *
   * @throws IOException if the rename failed for any reason
   */
  public void renameTo(Path target) throws IOException {
    checkSameFileSystem(target);
    fileSystem.renameTo(this, target);
  }

  /**
   * Returns the size in bytes of the file denoted by the current path, following symbolic links.
   *
   * <p>The size of a directory or special file is undefined and should not be used.
   *
   * @throws FileNotFoundException if the file denoted by the current path does not exist
   * @throws IOException if the file's metadata could not be read, or some other error occurred
   */
  public long getFileSize() throws IOException, FileNotFoundException {
    return fileSystem.getFileSize(this, true);
  }

  /**
   * Returns the size in bytes of the file denoted by the current path.
   *
   * <p>The size of directory or special file is undefined. The size of a symbolic link is the
   * length of the name of its referent.
   *
   * @param followSymlinks if {@link Symlinks#FOLLOW}, and this path denotes a symbolic link, the
   *     link is deferenced until a file other than a symbol link is found
   * @throws FileNotFoundException if the file denoted by the current path does not exist
   * @throws IOException if the file's metadata could not be read, or some other error occurred
   */
  public long getFileSize(Symlinks followSymlinks) throws IOException, FileNotFoundException {
    return fileSystem.getFileSize(this, followSymlinks.toBoolean());
  }

  /**
   * Deletes the file denoted by this path, not following symbolic links. Returns normally iff the
   * file doesn't exist after the call: true if this call deleted the file, false if the file
   * already didn't exist. Throws an exception if the file could not be deleted for any reason.
   *
   * @return true iff the file was actually deleted by this call
   * @throws IOException if the deletion failed but the file was present prior to the call
   */
  public boolean delete() throws IOException {
    return fileSystem.delete(this);
  }

  /**
   * Deletes all directory trees recursively beneath this path and removes the path as well.
   *
   * @throws IOException if the hierarchy cannot be removed successfully
   */
  public void deleteTree() throws IOException {
    fileSystem.deleteTree(this);
  }

  /**
   * Deletes all directory trees recursively beneath this path. Does nothing if the path is not a
   * directory.
   *
   * @throws IOException if the hierarchy cannot be removed successfully
   */
  public void deleteTreesBelow() throws IOException {
    fileSystem.deleteTreesBelow(this);
  }

  /**
   * Returns the last modification time of the file, in milliseconds since the UNIX epoch, of the
   * file denoted by the current path, following symbolic links.
   *
   * <p>Caveat: many filesystems store file times in seconds, so do not rely on the millisecond
   * precision.
   *
   * @throws IOException if the operation failed for any reason
   */
  public long getLastModifiedTime() throws IOException {
    return fileSystem.getLastModifiedTime(this, true);
  }

  /**
   * Returns the last modification time of the file, in milliseconds since the UNIX epoch, of the
   * file denoted by the current path.
   *
   * <p>Caveat: many filesystems store file times in seconds, so do not rely on the millisecond
   * precision.
   *
   * @param followSymlinks if {@link Symlinks#FOLLOW}, and this path denotes a symbolic link, the
   *     link is dereferenced until a file other than a symbolic link is found
   * @throws IOException if the modification time for the file could not be obtained for any reason
   */
  public long getLastModifiedTime(Symlinks followSymlinks) throws IOException {
    return fileSystem.getLastModifiedTime(this, followSymlinks.toBoolean());
  }

  /**
   * Sets the modification time of the file denoted by the current path. Follows symbolic links. If
   * newTime is -1, the current time according to the kernel is used; this may differ from the JVM's
   * clock.
   *
   * <p>Caveat: many filesystems store file times in seconds, so do not rely on the millisecond
   * precision.
   *
   * @param newTime time, in milliseconds since the UNIX epoch, or -1L, meaning use the kernel's
   *     current time
   * @throws IOException if the modification time for the file could not be set for any reason
   */
  public void setLastModifiedTime(long newTime) throws IOException {
    fileSystem.setLastModifiedTime(this, newTime);
  }

  /**
   * Returns the value of the given extended attribute name or null if the attribute does not exist
   * or the file system does not support extended attributes. Follows symlinks.
   */
  public byte[] getxattr(String name) throws IOException {
    return getxattr(name, Symlinks.FOLLOW);
  }

  /**
   * Returns the value of the given extended attribute name or null if the attribute does not exist
   * or the file system does not support extended attributes.
   *
   * @param followSymlinks whether to follow symlinks or not
   */
  public byte[] getxattr(String name, Symlinks followSymlinks) throws IOException {
    return fileSystem.getxattr(this, name, followSymlinks.toBoolean());
  }

  /**
   * Gets a fast digest for the given path, or {@code null} if there isn't one available. The digest
   * should be suitable for detecting changes to the file.
   */
  public byte[] getFastDigest() throws IOException {
    return fileSystem.getFastDigest(this);
  }

  /**
   * Returns the digest of the file denoted by the current path, following symbolic links.
   *
   * @return a new byte array containing the file's digest
   * @throws IOException if the digest could not be computed for any reason
   */
  public byte[] getDigest() throws IOException {
    return fileSystem.getDigest(this);
  }

  /**
   * Return a string representation, as hexadecimal digits, of some hash of the directory.
   *
   * <p>The hash itself is computed according to the design document
   * https://github.com/bazelbuild/proposals/blob/master/designs/2018-07-13-repository-hashing.md
   * and takes enough information into account, to detect the typical non-reproducibility
   * of source-like repository rules, while leaving out what will change from invocation to
   * invocation of a repository rule (in particular file owners) and can reasonably be ignored
   * when considering if a repository is "the same source tree".
   *
   * @return a string representation of the bash of the directory
   * @throws IOException if the digest could not be computed for any reason
   */
  public String getDirectoryDigest() throws IOException {
    List<String> entries = new ArrayList<String>(fileSystem.getDirectoryEntries(this));
    Collections.sort(entries);
    Hasher hasher = fileSystem.getDigestFunction().getHashFunction().newHasher();
    for (String entry : entries) {
      Path path = this.getChild(entry);
      FileStatus stat = path.stat(Symlinks.NOFOLLOW);
      hasher.putUnencodedChars(entry);
      if (stat.isFile()) {
        if (path.isExecutable()) {
          hasher.putChar('x');
        } else {
          hasher.putChar('-');
        }
        hasher.putBytes(path.getDigest());
      } else if (stat.isDirectory()) {
        hasher.putChar('d').putUnencodedChars(path.getDirectoryDigest());
      } else if (stat.isSymbolicLink()) {
        PathFragment link = path.readSymbolicLink();
        if (link.isAbsolute()) {
          try {
            Path resolved = path.resolveSymbolicLinks();
            if (resolved.isFile()) {
              if (resolved.isExecutable()) {
                hasher.putChar('x');
              } else {
                hasher.putChar('-');
              }
              hasher.putBytes(resolved.getDigest());
            } else {
              // link to a non-file: include the link itself in the hash
              hasher.putChar('l').putUnencodedChars(link.toString());
            }
          } catch (IOException e) {
            // dangling link: include the link itself in the hash
            hasher.putChar('l').putUnencodedChars(link.toString());
          }
        } else {
          // relative link: include the link itself in the hash
          hasher.putChar('l').putUnencodedChars(link.toString());
        }
      } else {
        // Neither file, nor directory, nor symlink. So do not include further information
        // in the hash, asuming it will not be used during the BUILD anyway.
        hasher.putChar('s');
      }
    }
    return hasher.hash().toString();
  }

  /**
   * Opens the file denoted by this path, following symbolic links, for reading, and returns an
   * input stream to it.
   *
   * @throws IOException if the file was not found or could not be opened for reading
   */
  public InputStream getInputStream() throws IOException {
    return fileSystem.getInputStream(this);
  }

  /**
   * Returns a java.io.File representation of this path.
   *
   * <p>Caveat: the result may be useless if this path's getFileSystem() is not
   * the UNIX filesystem.
   */
  public File getPathFile() {
    return new File(getPathString());
  }

  /**
   * Returns true if the file denoted by the current path, following symbolic links, is writable for
   * the current user.
   *
   * @throws FileNotFoundException if the file does not exist, a dangling symbolic link was
   *     encountered, or the file's metadata could not be read
   */
  public boolean isWritable() throws IOException, FileNotFoundException {
    return fileSystem.isWritable(this);
  }

  /**
   * Sets the read permissions of the file denoted by the current path, following symbolic links.
   * Permissions apply to the current user.
   *
   * @param readable if true, the file is set to readable; otherwise the file is made non-readable
   * @throws FileNotFoundException if the file does not exist
   * @throws IOException If the action cannot be taken (ie. permissions)
   */
  public void setReadable(boolean readable) throws IOException, FileNotFoundException {
    fileSystem.setReadable(this, readable);
  }

  /**
   * Sets the write permissions of the file denoted by the current path, following symbolic links.
   * Permissions apply to the current user.
   *
   * <p>TODO(bazel-team): (2009) what about owner/group/others?
   *
   * @param writable if true, the file is set to writable; otherwise the file is made non-writable
   * @throws FileNotFoundException if the file does not exist
   * @throws IOException If the action cannot be taken (ie. permissions)
   */
  public void setWritable(boolean writable) throws IOException, FileNotFoundException {
    fileSystem.setWritable(this, writable);
  }

  /**
   * Returns true iff the file specified by the current path, following symbolic links, is
   * executable by the current user.
   *
   * @throws FileNotFoundException if the file does not exist or a dangling symbolic link was
   *     encountered
   * @throws IOException if some other I/O error occurred
   */
  public boolean isExecutable() throws IOException, FileNotFoundException {
    return fileSystem.isExecutable(this);
  }

  /**
   * Returns true iff the file specified by the current path, following symbolic links, is readable
   * by the current user.
   *
   * @throws FileNotFoundException if the file does not exist or a dangling symbolic link was
   *     encountered
   * @throws IOException if some other I/O error occurred
   */
  public boolean isReadable() throws IOException, FileNotFoundException {
    return fileSystem.isReadable(this);
  }

  /**
   * Sets the execute permission on the file specified by the current path, following symbolic
   * links. Permissions apply to the current user.
   *
   * @throws FileNotFoundException if the file does not exist or a dangling symbolic link was
   *     encountered
   * @throws IOException if the metadata change failed, for example because of permissions
   */
  public void setExecutable(boolean executable) throws IOException, FileNotFoundException {
    fileSystem.setExecutable(this, executable);
  }

  /**
   * Sets the permissions on the file specified by the current path, following symbolic links. If
   * permission changes on this path's {@link FileSystem} are slow (e.g. one syscall per change),
   * this method should aim to be faster than setting each permission individually. If this path's
   * {@link FileSystem} does not support group and others permissions, those bits will be ignored.
   *
   * @throws FileNotFoundException if the file does not exist or a dangling symbolic link was
   *     encountered
   * @throws IOException if the metadata change failed, for example because of permissions
   */
  public void chmod(int mode) throws IOException {
    fileSystem.chmod(this, mode);
  }

  public void prefetchPackageAsync(int maxDirs) {
    fileSystem.prefetchPackageAsync(this, maxDirs);
  }

  private void checkSameFileSystem(Path that) {
    if (this.fileSystem != that.fileSystem) {
      throw new IllegalArgumentException(
          "Files are on different filesystems: " + this + ", " + that);
    }
  }

  private void writeObject(ObjectOutputStream out) throws IOException {
    Preconditions.checkState(
        fileSystem == fileSystemForSerialization, "%s %s", fileSystem, fileSystemForSerialization);
    out.writeUTF(path);
  }

  private void readObject(ObjectInputStream in) throws IOException {
    path = in.readUTF();
    fileSystem = fileSystemForSerialization;
    driveStrLength = OS.getDriveStrLength(path);
  }
}
