// Copyright 2019 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.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.nio.channels.ReadableByteChannel;
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, 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);
  }

  /** 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);
  }

  /**
   * Opens the file denoted by this path, following symbolic links, for reading, and returns a file
   * channel for it.
   *
   * @throws IOException if the file was not found or could not be opened for reading
   */
  public ReadableByteChannel createReadableByteChannel() throws IOException {
    return fileSystem.createReadableByteChannel(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);
  }
}
