// Copyright (C) 2008 The Android Open Source Project
//
// 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.gerrit.server.git;

import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.Project.NameKey;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collections;
import java.util.EnumSet;
import java.util.NavigableSet;
import java.util.TreeSet;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.lib.RepositoryCacheConfig;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.WindowCacheConfig;
import org.eclipse.jgit.util.FS;

/** Manages Git repositories stored on the local filesystem. */
@Singleton
public class LocalDiskRepositoryManager implements GitRepositoryManager {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static class LocalDiskRepositoryManagerModule extends LifecycleModule {
    @Override
    protected void configure() {
      listener().to(LocalDiskRepositoryManager.Lifecycle.class);
    }
  }

  public static class Lifecycle implements LifecycleListener {
    private final Config serverConfig;

    @Inject
    Lifecycle(@GerritServerConfig Config cfg) {
      this.serverConfig = cfg;
    }

    @Override
    public void start() {
      RepositoryCacheConfig repoCacheCfg = new RepositoryCacheConfig();
      repoCacheCfg.fromConfig(serverConfig);
      repoCacheCfg.install();

      WindowCacheConfig cfg = new WindowCacheConfig();
      cfg.fromConfig(serverConfig);
      if (serverConfig.getString("core", null, "streamFileThreshold") == null) {
        long mx = Runtime.getRuntime().maxMemory();
        int limit =
            (int)
                Math.min(
                    mx / 4, // don't use more than 1/4 of the heap.
                    2047 << 20); // cannot exceed array length
        if ((5 << 20) < limit && limit % (1 << 20) != 0) {
          // If the limit is at least 5 MiB but is not a whole multiple
          // of MiB round up to the next one full megabyte. This is a very
          // tiny memory increase in exchange for nice round units.
          limit = ((limit / (1 << 20)) + 1) << 20;
        }

        String desc;
        if (limit % (1 << 20) == 0) {
          desc = String.format("%dm", limit / (1 << 20));
        } else if (limit % (1 << 10) == 0) {
          desc = String.format("%dk", limit / (1 << 10));
        } else {
          desc = String.format("%d", limit);
        }
        logger.atInfo().log("Defaulting core.streamFileThreshold to %s", desc);
        cfg.setStreamFileThreshold(limit);
      }
      cfg.install();
    }

    @Override
    public void stop() {}
  }

  private final Path basePath;

  @Inject
  LocalDiskRepositoryManager(SitePaths site, @GerritServerConfig Config cfg) {
    basePath = site.resolve(cfg.getString("gerrit", null, "basePath"));
    if (basePath == null) {
      throw new IllegalStateException("gerrit.basePath must be configured");
    }
  }

  /**
   * Return the basePath under which the specified project is stored.
   *
   * @param name the name of the project
   * @return base directory
   */
  public Path getBasePath(Project.NameKey name) {
    return basePath;
  }

  @Override
  public Status getRepositoryStatus(NameKey name) {
    if (isUnreasonableName(name)) {
      return Status.NON_EXISTENT;
    }
    Path path = getBasePath(name);
    File dir = FileKey.resolve(path.resolve(name.get()).toFile(), FS.DETECTED);
    if (dir == null) {
      return Status.NON_EXISTENT;
    }
    Repository repo;
    try {
      // Try to open with mustExist, so that it does not attempt to create a repository.
      repo = RepositoryCache.open(FileKey.lenient(dir, FS.DETECTED), /*mustExist=*/ true);
    } catch (RepositoryNotFoundException e) {
      return Status.NON_EXISTENT;
    } catch (IOException e) {
      return Status.UNAVAILABLE;
    }
    // If object database does not exist, the repository is unusable
    return repo.getObjectDatabase().exists() ? Status.ACTIVE : Status.UNAVAILABLE;
  }

  @Override
  public Repository openRepository(Project.NameKey name) throws RepositoryNotFoundException {
    return openRepository(getBasePath(name), name);
  }

  private Repository openRepository(Path path, Project.NameKey name)
      throws RepositoryNotFoundException {
    if (isUnreasonableName(name)) {
      throw new RepositoryNotFoundException("Invalid name: " + name);
    }
    FileKey loc = FileKey.lenient(path.resolve(name.get()).toFile(), FS.DETECTED);
    try {
      return RepositoryCache.open(loc);
    } catch (IOException e) {
      throw new RepositoryNotFoundException("Cannot open repository " + name, e);
    }
  }

  @Override
  public Repository createRepository(Project.NameKey name)
      throws RepositoryNotFoundException, RepositoryExistsException, IOException {
    if (isUnreasonableName(name)) {
      throw new RepositoryNotFoundException("Invalid name: " + name);
    }

    Path path = getBasePath(name);
    File dir = FileKey.resolve(path.resolve(name.get()).toFile(), FS.DETECTED);
    if (dir != null) {
      // Already exists on disk, use the repository we found.
      //
      Project.NameKey onDiskName = getProjectName(path, dir.getCanonicalFile().toPath());

      if (!onDiskName.equals(name)) {
        throw new RepositoryCaseMismatchException(name);
      }
      throw new RepositoryExistsException(name);
    }

    // It doesn't exist under any of the standard permutations
    // of the repository name, so prefer the standard bare name.
    //
    String n = name.get() + Constants.DOT_GIT_EXT;
    FileKey loc = FileKey.exact(path.resolve(n).toFile(), FS.DETECTED);

    try {
      Repository db = RepositoryCache.open(loc, false);
      db.create(true /* bare */);

      StoredConfig config = db.getConfig();
      config.setBoolean(
          ConfigConstants.CONFIG_CORE_SECTION,
          null,
          ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES,
          true);
      config.save();

      // JGit only writes to the reflog for refs/meta/config if the log file
      // already exists.
      //
      File metaConfigLog = new File(db.getDirectory(), "logs/" + RefNames.REFS_CONFIG);
      if (!metaConfigLog.getParentFile().mkdirs() || !metaConfigLog.createNewFile()) {
        logger.atSevere().log(
            "Failed to create ref log for %s in repository %s", RefNames.REFS_CONFIG, name);
      }

      return db;
    } catch (IOException e) {
      throw new RepositoryNotFoundException("Cannot create repository " + name, e);
    }
  }

  @Override
  public Boolean canPerformGC() {
    return true;
  }

  private boolean isUnreasonableName(Project.NameKey nameKey) {
    final String name = nameKey.get();

    return name.length() == 0 // no empty paths
        || name.charAt(name.length() - 1) == '/' // no suffix
        || name.indexOf('\\') >= 0 // no windows/dos style paths
        || name.charAt(0) == '/' // no absolute paths
        || new File(name).isAbsolute() // no absolute paths
        || name.startsWith("../") // no "l../etc/passwd"
        || name.contains("/../") // no "foo/../etc/passwd"
        || name.contains("/./") // "foo/./foo" is insane to ask
        || name.contains("//") // windows UNC path can be "//..."
        || name.contains(".git/") // no path segments that end with '.git' as "foo.git/bar"
        || name.contains("?") // common unix wildcard
        || name.contains("%") // wildcard or string parameter
        || name.contains("*") // wildcard
        || name.contains(":") // Could be used for absolute paths in windows?
        || name.contains("<") // redirect input
        || name.contains(">") // redirect output
        || name.contains("|") // pipe
        || name.contains("$") // dollar sign
        || name.contains("\r") // carriage return
        || name.contains("/+") // delimiter in /changes/
        || name.contains("~"); // delimiter in /changes/
  }

  @Override
  public NavigableSet<Project.NameKey> list() {
    ProjectVisitor visitor = new ProjectVisitor(basePath);
    scanProjects(visitor);
    return Collections.unmodifiableNavigableSet(visitor.found);
  }

  protected void scanProjects(ProjectVisitor visitor) {
    try {
      Files.walkFileTree(
          visitor.startFolder,
          EnumSet.of(FileVisitOption.FOLLOW_LINKS),
          Integer.MAX_VALUE,
          visitor);
    } catch (IOException e) {
      logger.atSevere().withCause(e).log(
          "Error walking repository tree %s", visitor.startFolder.toAbsolutePath());
    }
  }

  private static Project.NameKey getProjectName(Path startFolder, Path p) {
    String projectName = startFolder.relativize(p).toString();
    if (File.separatorChar != '/') {
      projectName = projectName.replace(File.separatorChar, '/');
    }
    if (projectName.endsWith(Constants.DOT_GIT_EXT)) {
      int newLen = projectName.length() - Constants.DOT_GIT_EXT.length();
      projectName = projectName.substring(0, newLen);
    }
    return Project.nameKey(projectName);
  }

  protected class ProjectVisitor extends SimpleFileVisitor<Path> {
    private final NavigableSet<Project.NameKey> found = new TreeSet<>();
    private Path startFolder;

    public ProjectVisitor(Path startFolder) {
      setStartFolder(startFolder);
    }

    public void setStartFolder(Path startFolder) {
      this.startFolder = startFolder;
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
        throws IOException {
      if (!dir.equals(startFolder) && isRepo(dir)) {
        addProject(dir);
        return FileVisitResult.SKIP_SUBTREE;
      }
      return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException e) {
      logger.atWarning().log("%s", e.getMessage());
      return FileVisitResult.CONTINUE;
    }

    private boolean isRepo(Path p) {
      String name = p.getFileName().toString();
      return !name.equals(Constants.DOT_GIT)
          && (name.endsWith(Constants.DOT_GIT_EXT)
              || FileKey.isGitRepository(p.toFile(), FS.DETECTED));
    }

    private void addProject(Path p) {
      Project.NameKey nameKey = getProjectName(startFolder, p);
      if (getBasePath(nameKey).equals(startFolder)) {
        if (isUnreasonableName(nameKey)) {
          logger.atWarning().log("Ignoring unreasonably named repository %s", p.toAbsolutePath());
        } else {
          found.add(nameKey);
        }
      }
    }
  }
}
