/*
 * Copyright 2012-present Facebook, Inc.
 *
 * 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.facebook.buck.io;

import com.facebook.buck.util.environment.Platform;
import com.facebook.buck.zip.CustomZipEntry;
import com.facebook.buck.zip.CustomZipOutputStream;
import com.facebook.buck.zip.ZipOutputStreams;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteStreams;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.channels.Channels;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;

/**
 * An injectable service for interacting with the filesystem relative to the project root.
 */
public class ProjectFilesystem {

  /**
   * Controls the behavior of how the source should be treated when copying.
   */
  public enum CopySourceMode {
      /**
       * Copy the single source file into the destination path.
       */
      FILE,

      /**
       * Treat the source as a directory and copy each file inside it
       * to the destination path, which must be a directory.
       */
      DIRECTORY_CONTENTS_ONLY,

      /**
       * Treat the source as a directory. Copy the directory and its
       * contents to the destination path, which must be a directory.
       */
      DIRECTORY_AND_CONTENTS,
  }

  private final Path projectRoot;

  private final Function<Path, Path> pathAbsolutifier;

  private final ImmutableSet<Path> ignorePaths;

  // Defaults to false, and so paths should be valid.
  @VisibleForTesting
  protected boolean ignoreValidityOfPaths;

  public ProjectFilesystem(Path projectRoot) {
    this(projectRoot, ImmutableSet.<Path>of());
  }

  /**
   * There should only be one {@link ProjectFilesystem} created per process.
   * <p>
   * When creating a {@code ProjectFilesystem} for a test, rather than create a filesystem with an
   * arbitrary argument for the project root, such as {@code new File(".")}, prefer the creation of
   * a mock filesystem via EasyMock instead. Note that there are cases (such as integration tests)
   * where specifying {@code new File(".")} as the project root might be the appropriate thing.
   */
  public ProjectFilesystem(Path projectRoot, ImmutableSet<Path> ignorePaths) {
    this(projectRoot.getFileSystem(), projectRoot, ignorePaths);
  }

  protected ProjectFilesystem(FileSystem vfs, Path projectRoot, ImmutableSet<Path> ignorePaths) {
    Preconditions.checkArgument(Files.isDirectory(projectRoot));
    Preconditions.checkState(vfs.equals(projectRoot.getFileSystem()));
    this.projectRoot = projectRoot;
    this.pathAbsolutifier = new Function<Path, Path>() {
      @Override
      public Path apply(Path path) {
        return resolve(path);
      }
    };
    this.ignorePaths = MorePaths.filterForSubpaths(ignorePaths, this.projectRoot);
    this.ignoreValidityOfPaths = false;
  }

  public Path getRootPath() {
    return projectRoot;
  }

  /**
   * @return the specified {@code path} resolved against {@link #getRootPath()} to an absolute path.
   */
  public Path resolve(Path path) {
    return getRootPath().resolve(path).toAbsolutePath().normalize();
  }

  public Path resolve(String path) {
    return getRootPath().resolve(path).toAbsolutePath().normalize();
  }

  /**
   * @return A {@link Function} that applies {@link #resolve(Path)} to its parameter.
   */
  public Function<Path, Path> getAbsolutifier() {
    return pathAbsolutifier;
  }

  /**
   * @return A {@link ImmutableSet} of {@link Path} objects to have buck ignore.  All paths will be
   *     relative to the {@link ProjectFilesystem#getRootPath()}.
   */
  public ImmutableSet<Path> getIgnorePaths() {
    return ignorePaths;
  }

  /**
   * // @deprecated Prefer operating on {@code Path}s directly, replaced by
   *    {@link #getPathForRelativePath(java.nio.file.Path)}.
   */
  public File getFileForRelativePath(String pathRelativeToProjectRoot) {
    return pathRelativeToProjectRoot.isEmpty()
        ? projectRoot.toFile()
        : getPathForRelativePath(Paths.get(pathRelativeToProjectRoot)).toFile();
  }

  /**
   * // @deprecated Prefer operating on {@code Path}s directly, replaced by
   *    {@link #getPathForRelativePath(java.nio.file.Path)}.
   */
  public File getFileForRelativePath(Path pathRelativeToProjectRoot) {
    return getPathForRelativePath(pathRelativeToProjectRoot).toFile();
  }

  public Path getPathForRelativePath(Path pathRelativeToProjectRoot) {
    return projectRoot.resolve(pathRelativeToProjectRoot);
  }

  /**
   * As {@link #getFileForRelativePath(java.nio.file.Path)}, but with the added twist that the
   * existence of the path is checked before returning.
   */
  public Path getPathForRelativeExistingPath(Path pathRelativeToProjectRoot) {
    Path file = getPathForRelativePath(pathRelativeToProjectRoot);

    if (ignoreValidityOfPaths) {
      return file;
    }

    // TODO(mbolin): Eliminate this temporary exemption for symbolic links.
    if (Files.isSymbolicLink(file)) {
      return file;
    }

    if (!Files.exists(file)) {
      throw new RuntimeException(
          String.format("Not an ordinary file: '%s'.", pathRelativeToProjectRoot));
    }

    return file;
  }

  public boolean exists(Path pathRelativeToProjectRoot) {
    return Files.exists(getPathForRelativePath(pathRelativeToProjectRoot));
  }

  public long getFileSize(Path pathRelativeToProjectRoot) throws IOException {
    Path path = getPathForRelativePath(pathRelativeToProjectRoot);
    if (!Files.isRegularFile(path)) {
      throw new IOException("Cannot get size of " + path + " because it is not an ordinary file.");
    }
    return Files.size(path);
  }

  /**
   * Deletes a file specified by its path relative to the project root.
   * @param pathRelativeToProjectRoot path to the file
   * @return true if the file was successfully deleted, false otherwise
   */
  public boolean deleteFileAtPath(Path pathRelativeToProjectRoot) {
    try {
      Files.delete(getPathForRelativePath(pathRelativeToProjectRoot));
      return true;
    } catch (IOException e) {
      return false;
    }
  }

  public Properties readPropertiesFile(Path pathToPropertiesFileRelativeToProjectRoot)
      throws IOException {
    Properties properties = new Properties();
    Path propertiesFile = getPathForRelativePath(pathToPropertiesFileRelativeToProjectRoot);
    if (Files.exists(propertiesFile)) {
      properties.load(Files.newBufferedReader(propertiesFile, Charsets.UTF_8));
      return properties;
    } else {
      throw new FileNotFoundException(propertiesFile.toString());
    }
  }

  /**
   * Checks whether there is a normal file at the specified path.
   */
  public boolean isFile(Path pathRelativeToProjectRoot) {
    return Files.isRegularFile(
        getPathForRelativePath(pathRelativeToProjectRoot));
  }

  public boolean isHidden(Path pathRelativeToProjectRoot) throws IOException {
    return Files.isHidden(getPathForRelativePath(pathRelativeToProjectRoot));
  }

  /**
   * Similar to {@link #walkFileTree(Path, FileVisitor)} except this takes in a path relative to
   * the project root.
   */
  public void walkRelativeFileTree(
      Path pathRelativeToProjectRoot,
      final FileVisitor<Path> fileVisitor) throws IOException {
    walkRelativeFileTree(pathRelativeToProjectRoot,
        EnumSet.of(FileVisitOption.FOLLOW_LINKS),
        fileVisitor);
  }

  /**
   * Walks a project-root relative file tree with a visitor and visit options.
   */
  public void walkRelativeFileTree(
      Path pathRelativeToProjectRoot,
      EnumSet<FileVisitOption> visitOptions,
      final FileVisitor<Path> fileVisitor) throws IOException {
    Path rootPath = getPathForRelativePath(pathRelativeToProjectRoot);
    Files.walkFileTree(
        rootPath,
        visitOptions,
        Integer.MAX_VALUE,
        new FileVisitor<Path>() {
          @Override
          public FileVisitResult preVisitDirectory(
              Path dir, BasicFileAttributes attrs) throws IOException {
            return fileVisitor.preVisitDirectory(projectRoot.relativize(dir), attrs);
          }

          @Override
          public FileVisitResult visitFile(
              Path file, BasicFileAttributes attrs) throws IOException {
            return fileVisitor.visitFile(projectRoot.relativize(file), attrs);
          }

          @Override
          public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
            return fileVisitor.visitFileFailed(projectRoot.relativize(file), exc);
          }

          @Override
          public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            return fileVisitor.postVisitDirectory(projectRoot.relativize(dir), exc);
          }
        });
  }

  /**
   * Allows {@link Files#walkFileTree} to be faked in tests.
   */
  public void walkFileTree(Path root, FileVisitor<Path> fileVisitor) throws IOException {
    Files.walkFileTree(root, fileVisitor);
  }

  public ImmutableSet<Path> getFilesUnderPath(Path pathRelativeToProjectRoot) throws IOException {
    return getFilesUnderPath(pathRelativeToProjectRoot, Predicates.<Path>alwaysTrue());
  }

  public ImmutableSet<Path> getFilesUnderPath(
      Path pathRelativeToProjectRoot,
      Predicate<Path> predicate) throws IOException {
    return getFilesUnderPath(
        pathRelativeToProjectRoot,
        predicate,
        EnumSet.of(FileVisitOption.FOLLOW_LINKS));
  }

  public ImmutableSet<Path> getFilesUnderPath(
      Path pathRelativeToProjectRoot,
      final Predicate<Path> predicate,
      EnumSet<FileVisitOption> visitOptions) throws IOException {
    final ImmutableSet.Builder<Path> paths = ImmutableSet.builder();
    walkRelativeFileTree(
        pathRelativeToProjectRoot,
        visitOptions,
        new SimpleFileVisitor<Path>() {
          @Override
          public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) {
            if (predicate.apply(path)) {
              paths.add(path);
            }
            return FileVisitResult.CONTINUE;
          }
        });
    return paths.build();
  }

  /**
   * Allows {@link Files#isDirectory} to be faked in tests.
   */
  public boolean isDirectory(Path child, LinkOption... linkOptions) {
    return Files.isDirectory(child, linkOptions);
  }

  /**
   * Allows {@link java.io.File#listFiles} to be faked in tests.
   *
   * // @deprecated Replaced by {@link #getDirectoryContents}
   */
  public File[] listFiles(Path pathRelativeToProjectRoot) throws IOException {
    Collection<Path> paths = getDirectoryContents(pathRelativeToProjectRoot);

    File[] result = new File[paths.size()];
    return Collections2.transform(paths, new Function<Path, File>() {
      @Override
      public File apply(Path input) {
        return input.toFile();
      }
    }).toArray(result);
  }

  public ImmutableCollection<Path> getDirectoryContents(Path pathRelativeToProjectRoot)
      throws IOException {
    Path path = getPathForRelativePath(pathRelativeToProjectRoot);
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
      return ImmutableList.copyOf(stream);
    }
  }

  @VisibleForTesting
  protected PathListing.PathModifiedTimeFetcher getLastModifiedTimeFetcher() {
    return new PathListing.PathModifiedTimeFetcher() {
        @Override
        public FileTime getLastModifiedTime(Path path) throws IOException {
          return FileTime.fromMillis(ProjectFilesystem.this.getLastModifiedTime(path));
        }
    };
  }

  /**
   * Returns the files inside {@code pathRelativeToProjectRoot} which match
   * {@code globPattern}, ordered in descending last modified time order.
   */
  public ImmutableSortedSet<Path> getSortedMatchingDirectoryContents(
      Path pathRelativeToProjectRoot,
      String globPattern)
    throws IOException {
    Path path = getPathForRelativePath(pathRelativeToProjectRoot);
    return PathListing.listMatchingPaths(
        path,
        globPattern,
        getLastModifiedTimeFetcher());
  }

  public long getLastModifiedTime(Path pathRelativeToProjectRoot) throws IOException {
    Path path = getPathForRelativePath(pathRelativeToProjectRoot);
    return Files.getLastModifiedTime(path).toMillis();
  }

  /**
   * Recursively delete everything under the specified path.
   */
  public void rmdir(Path pathRelativeToProjectRoot) throws IOException {
    MoreFiles.rmdir(resolve(pathRelativeToProjectRoot));
  }

  /**
   * Resolves the relative path against the project root and then calls
   * {@link Files#createDirectories(java.nio.file.Path,
   *            java.nio.file.attribute.FileAttribute[])}
   */
  public void mkdirs(Path pathRelativeToProjectRoot) throws IOException {
    Files.createDirectories(resolve(pathRelativeToProjectRoot));
  }

  /**
   * // @deprecated Prefer operating on {@code Path}s directly, replaced by
   *  {@link #createParentDirs(java.nio.file.Path)}.
   */
  public void createParentDirs(String pathRelativeToProjectRoot) throws IOException {
    Path file = getPathForRelativePath(Paths.get(pathRelativeToProjectRoot));
    mkdirs(file.getParent());
  }

  /**
   * @param pathRelativeToProjectRoot Must identify a file, not a directory. (Unfortunately, we have
   *     no way to assert this because the path is not expected to exist yet.)
   */
  public void createParentDirs(Path pathRelativeToProjectRoot) throws IOException {
    Path file = resolve(pathRelativeToProjectRoot);
    Path directory = file.getParent();
    mkdirs(directory);
  }

  /**
   * Writes each line in {@code lines} with a trailing newline to a file at the specified path.
   * <p>
   * The parent path of {@code pathRelativeToProjectRoot} must exist.
   */
  public void writeLinesToPath(
      Iterable<String> lines,
      Path pathRelativeToProjectRoot,
      FileAttribute<?>... attrs)
      throws IOException {
    try (Writer writer =
         new BufferedWriter(
             new OutputStreamWriter(newFileOutputStream(pathRelativeToProjectRoot, attrs)))) {
      for (String line : lines) {
        writer.write(line);
        writer.write('\n');
      }
    }
  }

  public void writeContentsToPath(
      String contents,
      Path pathRelativeToProjectRoot,
      FileAttribute<?>... attrs)
      throws IOException {
    writeBytesToPath(contents.getBytes(Charsets.UTF_8), pathRelativeToProjectRoot, attrs);
  }

  public void writeBytesToPath(
      byte[] bytes,
      Path pathRelativeToProjectRoot,
      FileAttribute<?>... attrs) throws IOException {
    try (OutputStream outputStream = newFileOutputStream(pathRelativeToProjectRoot, attrs)) {
      outputStream.write(bytes);
    }
  }

  public OutputStream newFileOutputStream(
      Path pathRelativeToProjectRoot,
      FileAttribute<?>... attrs)
    throws IOException {
    return new BufferedOutputStream(
        Channels.newOutputStream(
            Files.newByteChannel(
                getPathForRelativePath(pathRelativeToProjectRoot),
                ImmutableSet.<OpenOption>of(
                    StandardOpenOption.CREATE,
                    StandardOpenOption.TRUNCATE_EXISTING,
                    StandardOpenOption.WRITE),
                attrs)));
  }

  public <A extends BasicFileAttributes> A readAttributes(
      Path pathRelativeToProjectRoot,
      Class<A> type,
      LinkOption... options)
    throws IOException {
    return Files.readAttributes(
        getPathForRelativePath(pathRelativeToProjectRoot), type, options);
  }

  public InputStream newFileInputStream(Path pathRelativeToProjectRoot)
    throws IOException {
    return new BufferedInputStream(
        Files.newInputStream(getPathForRelativePath(pathRelativeToProjectRoot)));
  }

  /**
   * @param inputStream Source of the bytes. This method does not close this stream.
   */
  public void copyToPath(
      InputStream inputStream,
      Path pathRelativeToProjectRoot,
      CopyOption... options)
      throws IOException {
    Files.copy(inputStream, getPathForRelativePath(pathRelativeToProjectRoot),
        options);
  }

  public Optional<String> readFileIfItExists(Path pathRelativeToProjectRoot) {
    Path fileToRead = getPathForRelativePath(pathRelativeToProjectRoot);
    return readFileIfItExists(fileToRead, pathRelativeToProjectRoot.toString());
  }

  private Optional<String> readFileIfItExists(Path fileToRead, String pathRelativeToProjectRoot) {
    if (Files.isRegularFile(fileToRead)) {
      String contents;
      try {
        contents = new String(Files.readAllBytes(fileToRead), Charsets.UTF_8);
      } catch (IOException e) {
        // Alternatively, we could return Optional.absent(), though something seems suspicious if we
        // have already verified that fileToRead is a file and then we cannot read it.
        throw new RuntimeException("Error reading " + pathRelativeToProjectRoot, e);
      }
      return Optional.of(contents);
    } else {
      return Optional.absent();
    }
  }

  /**
   * Attempts to open the file for future read access. Returns {@link Optional#absent()} if the file
   * does not exist.
   */
  public Optional<Reader> getReaderIfFileExists(Path pathRelativeToProjectRoot) {
    Path fileToRead = getPathForRelativePath(pathRelativeToProjectRoot);
    if (Files.isRegularFile(fileToRead)) {
      try {
        return Optional.of(
            (Reader) new BufferedReader(
                new InputStreamReader(newFileInputStream(pathRelativeToProjectRoot))));
      } catch (Exception e) {
        throw new RuntimeException("Error reading " + pathRelativeToProjectRoot, e);
      }
    } else {
      return Optional.absent();
    }
  }

  /**
   * Attempts to read the first line of the file specified by the relative path. If the file does
   * not exist, is empty, or encounters an error while being read, {@link Optional#absent()} is
   * returned. Otherwise, an {@link Optional} with the first line of the file will be returned.
   *
   * // @deprecated PRefero operation on {@code Path}s directly, replaced by
   *  {@link #readFirstLine(java.nio.file.Path)}
   */
  public Optional<String> readFirstLine(String pathRelativeToProjectRoot) {
    return readFirstLine(Paths.get(pathRelativeToProjectRoot));
  }

  /**
   * Attempts to read the first line of the file specified by the relative path. If the file does
   * not exist, is empty, or encounters an error while being read, {@link Optional#absent()} is
   * returned. Otherwise, an {@link Optional} with the first line of the file will be returned.
   */
  public Optional<String> readFirstLine(Path pathRelativeToProjectRoot) {
    Path file = getPathForRelativePath(pathRelativeToProjectRoot);
    return readFirstLineFromFile(file);
  }

  /**
   * Attempts to read the first line of the specified file. If the file does not exist, is empty,
   * or encounters an error while being read, {@link Optional#absent()} is returned. Otherwise, an
   * {@link Optional} with the first line of the file will be returned.
   */
  public Optional<String> readFirstLineFromFile(Path file) {
    try {
      return Optional.fromNullable(
          Files.newBufferedReader(file, Charsets.UTF_8).readLine());
    } catch (IOException e) {
      // Because the file is not even guaranteed to exist, swallow the IOException.
      return Optional.absent();
    }
  }

  public List<String> readLines(Path pathRelativeToProjectRoot) throws IOException {
    Path file = getPathForRelativePath(pathRelativeToProjectRoot);
    return Files.readAllLines(file, Charsets.UTF_8);
  }

  /**
   * // @deprecated Prefer operation on {@code Path}s directly, replaced by
   *  {@link Files#newInputStream(java.nio.file.Path, java.nio.file.OpenOption...)}.
   */
  public InputStream getInputStreamForRelativePath(Path path) throws IOException {
    Path file = getPathForRelativePath(path);
    return Files.newInputStream(file);
  }

  public String computeSha1(Path pathRelativeToProjectRoot) throws IOException {
    Path fileToHash = getPathForRelativePath(pathRelativeToProjectRoot);
    return Hashing.sha1().hashBytes(Files.readAllBytes(fileToHash)).toString();
  }

  /**
   * @param event The event to be tested.
   * @return true if event is a path change notification.
   */
  public boolean isPathChangeEvent(WatchEvent<?> event) {
    return event.kind() == StandardWatchEventKinds.ENTRY_CREATE ||
        event.kind() == StandardWatchEventKinds.ENTRY_MODIFY ||
        event.kind() == StandardWatchEventKinds.ENTRY_DELETE;
  }

  public void copy(Path source, Path target, CopySourceMode sourceMode) throws IOException {
    switch (sourceMode) {
      case FILE:
        Files.copy(
            resolve(source),
            resolve(target),
            StandardCopyOption.REPLACE_EXISTING);
        break;
      case DIRECTORY_CONTENTS_ONLY:
        MoreFiles.copyRecursively(resolve(source), resolve(target));
        break;
      case DIRECTORY_AND_CONTENTS:
        MoreFiles.copyRecursively(resolve(source), resolve(target.resolve(source.getFileName())));
        break;
    }
  }

  public void move(Path source, Path target, CopyOption... options) throws IOException {
    Files.move(resolve(source), resolve(target), options);

  }

  public void copyFolder(Path source, Path target) throws IOException {
    copy(source, target, CopySourceMode.DIRECTORY_CONTENTS_ONLY);
  }

  public void copyFile(Path source, Path target) throws IOException {
    copy(source, target, CopySourceMode.FILE);
  }

  public void createSymLink(Path sourcePath, Path targetPath, boolean force)
      throws IOException {
    if (force) {
      Files.deleteIfExists(targetPath);
    }
    if (Platform.detect() == Platform.WINDOWS) {
      if (isDirectory(sourcePath)) {
        // Creating symlinks to directories on Windows requires escalated privileges. We're just
        // going to have to copy things recursively.
        MoreFiles.copyRecursively(sourcePath, targetPath);
      } else {
        Files.createLink(targetPath, sourcePath);
      }
    } else {
      Files.createSymbolicLink(targetPath, sourcePath);
    }
  }

  /**
   * Returns true if the file under {@code path} exists and is a symbolic
   * link, false otherwise.
   */
  public boolean isSymLink(Path path) throws IOException {
    return Files.isSymbolicLink(getPathForRelativePath(path));
  }

  /**
   * Takes a sequence of paths relative to the project root and writes a zip file to {@code out}
   * with the contents and structure that matches that of the specified paths.
   */
  public void createZip(Collection<Path> pathsToIncludeInZip, File out) throws IOException {
    createZip(pathsToIncludeInZip, out, ImmutableMap.<Path, String>of());
  }

  /**
   * Similar to {@link #createZip(Collection, File)}, but also takes a list of additional files to
   * write in the zip, including their contents, as a map.
   */
  public void createZip(
      Collection<Path> pathsToIncludeInZip,
      File out,
      ImmutableMap<Path, String> additionalFileContents) throws IOException {
    Preconditions.checkState(!Iterables.isEmpty(pathsToIncludeInZip));
    try (CustomZipOutputStream zip = ZipOutputStreams.newOutputStream(out)) {
      for (Path path : pathsToIncludeInZip) {
        Path full = getPathForRelativePath(path);
        File file = full.toFile();
        boolean isDirectory = isDirectory(full);

        String entryName = path.toString();
        if (isDirectory) {
          entryName += "/";
        }
        CustomZipEntry entry = new CustomZipEntry(entryName);

        // Support executable files.  If we detect this file is executable, store this
        // information as 0100 in the field typically used in zip implementations for
        // POSIX file permissions.  We'll use this information when unzipping.
        if (file.canExecute()) {
          entry.setExternalAttributes(
              MorePosixFilePermissions.toMode(
                  EnumSet.of(PosixFilePermission.OWNER_EXECUTE)) << 16);
        }

        zip.putNextEntry(entry);
        if (!isDirectory) {
          try (InputStream input = Files.newInputStream(getPathForRelativePath(path))) {
            ByteStreams.copy(input, zip);
          }
        }
        zip.closeEntry();
      }

      for (Map.Entry<Path, String> fileContentsEntry : additionalFileContents.entrySet()) {
        CustomZipEntry entry = new CustomZipEntry(fileContentsEntry.getKey().toString());
        zip.putNextEntry(entry);
        try (InputStream stream =
                 new ByteArrayInputStream(fileContentsEntry.getValue().getBytes(Charsets.UTF_8))) {
          ByteStreams.copy(stream, zip);
        }
        zip.closeEntry();
      }
    }
  }

  /**
   *
   * @param event the event to format.
   * @return the formatted event context string.
   */
  public String createContextString(WatchEvent<?> event) {
    if (isPathChangeEvent(event)) {
      Path path = (Path) event.context();
      return path.toAbsolutePath().normalize().toString();
    }
    return String.valueOf(event.context());
  }


  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }

    if (!(other instanceof ProjectFilesystem)) {
      return false;
    }

    ProjectFilesystem that = (ProjectFilesystem) other;

    return Objects.equals(projectRoot, that.projectRoot) &&
        Objects.equals(ignorePaths, that.ignorePaths);
  }

  @Override
  public int hashCode() {
    return Objects.hash(projectRoot, ignorePaths);
  }

  /**
   * @param path the path to check.
   * @return whether ignoredPaths contains path or any of its ancestors.
   */
  public boolean isIgnored(Path path) {
    for (Path ignoredPath : getIgnorePaths()) {
      if (path.startsWith(ignoredPath)) {
        return true;
      }
    }
    return false;
  }

  public Path createTempFile(
      Path directory,
      String prefix,
      String suffix,
      FileAttribute<?>... attrs)
      throws IOException {
    return Files.createTempFile(directory, prefix, suffix, attrs);
  }

}
