// Copyright (C) 2012 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.validators;

import static com.google.gerrit.reviewdb.client.RefNames.REFS_CHANGES;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_CONFIG;
import static org.eclipse.jgit.lib.Constants.R_HEADS;

import com.google.common.base.CharMatcher;
import com.google.gerrit.common.ChangeHookRunner.HookResult;
import com.google.gerrit.common.ChangeHooks;
import com.google.gerrit.common.FooterConstants;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.events.CommitReceivedEvent;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.git.ReceiveCommits;
import com.google.gerrit.server.git.ValidationError;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.RefControl;
import com.google.gerrit.server.ssh.SshInfo;
import com.google.gerrit.server.util.MagicBranch;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;

import com.jcraft.jsch.HostKey;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.FooterKey;
import org.eclipse.jgit.revwalk.FooterLine;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.util.SystemReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class CommitValidators {
  private static final Logger log = LoggerFactory
      .getLogger(CommitValidators.class);

  public interface Factory {
    CommitValidators create(RefControl refControl, SshInfo sshInfo,
        Repository repo);
  }

  private final PersonIdent gerritIdent;
  private final RefControl refControl;
  private final String canonicalWebUrl;
  private final String installCommitMsgHookCommand;
  private final SshInfo sshInfo;
  private final Repository repo;
  private final ChangeHooks hooks;
  private final DynamicSet<CommitValidationListener> commitValidationListeners;

  @Inject
  CommitValidators(@GerritPersonIdent final PersonIdent gerritIdent,
      @CanonicalWebUrl @Nullable final String canonicalWebUrl,
      @GerritServerConfig final Config config,
      final DynamicSet<CommitValidationListener> commitValidationListeners,
      final ChangeHooks hooks,
      @Assisted final SshInfo sshInfo,
      @Assisted final Repository repo, @Assisted final RefControl refControl) {
    this.gerritIdent = gerritIdent;
    this.refControl = refControl;
    this.canonicalWebUrl = canonicalWebUrl;
    this.installCommitMsgHookCommand =
        config.getString("gerrit", null, "installCommitMsgHookCommand");
    this.sshInfo = sshInfo;
    this.repo = repo;
    this.hooks = hooks;
    this.commitValidationListeners = commitValidationListeners;
  }

  public List<CommitValidationMessage> validateForReceiveCommits(
      CommitReceivedEvent receiveEvent, NoteMap rejectCommits)
      throws CommitValidationException {

    List<CommitValidationListener> validators = new LinkedList<>();

    validators.add(new UploadMergesPermissionValidator(refControl));
    validators.add(new AmendedGerritMergeCommitValidationListener(
        refControl, gerritIdent));
    validators.add(new AuthorUploaderValidator(refControl, canonicalWebUrl));
    validators.add(new CommitterUploaderValidator(refControl, canonicalWebUrl));
    validators.add(new SignedOffByValidator(refControl));
    if (MagicBranch.isMagicBranch(receiveEvent.command.getRefName())
        || ReceiveCommits.NEW_PATCHSET.matcher(
            receiveEvent.command.getRefName()).matches()) {
      validators.add(new ChangeIdValidator(refControl, canonicalWebUrl,
          installCommitMsgHookCommand, sshInfo));
    }
    validators.add(new ConfigValidator(refControl, repo));
    validators.add(new BannedCommitsValidator(rejectCommits));
    validators.add(new PluginCommitValidationListener(commitValidationListeners));

    List<CommitValidationMessage> messages = new LinkedList<>();

    try {
      for (CommitValidationListener commitValidator : validators) {
        messages.addAll(commitValidator.onCommitReceived(receiveEvent));
      }
    } catch (CommitValidationException e) {
      // Keep the old messages (and their order) in case of an exception
      messages.addAll(e.getMessages());
      throw new CommitValidationException(e.getMessage(), messages);
    }
    return messages;
  }

  public List<CommitValidationMessage> validateForGerritCommits(
      CommitReceivedEvent receiveEvent) throws CommitValidationException {

    List<CommitValidationListener> validators = new LinkedList<>();

    validators.add(new UploadMergesPermissionValidator(refControl));
    validators.add(new AmendedGerritMergeCommitValidationListener(
        refControl, gerritIdent));
    validators.add(new AuthorUploaderValidator(refControl, canonicalWebUrl));
    validators.add(new SignedOffByValidator(refControl));
    if (MagicBranch.isMagicBranch(receiveEvent.command.getRefName())
        || ReceiveCommits.NEW_PATCHSET.matcher(
            receiveEvent.command.getRefName()).matches()) {
      validators.add(new ChangeIdValidator(refControl, canonicalWebUrl,
          installCommitMsgHookCommand, sshInfo));
    }
    validators.add(new ConfigValidator(refControl, repo));
    validators.add(new PluginCommitValidationListener(commitValidationListeners));
    validators.add(new ChangeHookValidator(refControl, hooks));

    List<CommitValidationMessage> messages = new LinkedList<>();

    try {
      for (CommitValidationListener commitValidator : validators) {
        messages.addAll(commitValidator.onCommitReceived(receiveEvent));
      }
    } catch (CommitValidationException e) {
      // Keep the old messages (and their order) in case of an exception
      messages.addAll(e.getMessages());
      throw new CommitValidationException(e.getMessage(), messages);
    }
    return messages;
  }

  public static class ChangeIdValidator implements CommitValidationListener {
    private final ProjectControl projectControl;
    private final String canonicalWebUrl;
    private final String installCommitMsgHookCommand;
    private final SshInfo sshInfo;
    private final IdentifiedUser user;

    public ChangeIdValidator(RefControl refControl, String canonicalWebUrl,
        String installCommitMsgHookCommand, SshInfo sshInfo) {
      this.projectControl = refControl.getProjectControl();
      this.canonicalWebUrl = canonicalWebUrl;
      this.installCommitMsgHookCommand = installCommitMsgHookCommand;
      this.sshInfo = sshInfo;
      this.user = (IdentifiedUser) projectControl.getCurrentUser();
    }

    @Override
    public List<CommitValidationMessage> onCommitReceived(
        CommitReceivedEvent receiveEvent) throws CommitValidationException {
      final List<String> idList = receiveEvent.commit.getFooterLines(
          FooterConstants.CHANGE_ID);

      List<CommitValidationMessage> messages = new LinkedList<>();

      if (idList.isEmpty()) {
        if (projectControl.getProjectState().isRequireChangeID()) {
          String shortMsg = receiveEvent.commit.getShortMessage();
          String changeIdPrefix = FooterConstants.CHANGE_ID.getName() + ":";
          if (shortMsg.startsWith(changeIdPrefix)
              && shortMsg.substring(changeIdPrefix.length()).trim()
                  .matches("^I[0-9a-f]{8,}.*$")) {
            throw new CommitValidationException(
                "missing subject; Change-Id must be in commit message footer");
          } else {
            String errMsg = "missing Change-Id in commit message footer";
            messages.add(getMissingChangeIdErrorMsg(
                errMsg, receiveEvent.commit));
            throw new CommitValidationException(errMsg, messages);
          }
        }
      } else if (idList.size() > 1) {
        throw new CommitValidationException(
            "multiple Change-Id lines in commit message footer", messages);
      } else {
        final String v = idList.get(idList.size() - 1).trim();
        if (!v.matches("^I[0-9a-f]{8,}.*$")) {
          final String errMsg =
              "missing or invalid Change-Id line format in commit message footer";
          messages.add(
              getMissingChangeIdErrorMsg(errMsg, receiveEvent.commit));
          throw new CommitValidationException(errMsg, messages);
        }
      }
      return Collections.emptyList();
    }

    private CommitValidationMessage getMissingChangeIdErrorMsg(
        final String errMsg, final RevCommit c) {
      final String changeId = "Change-Id:";
      StringBuilder sb = new StringBuilder();
      sb.append("ERROR: ").append(errMsg);

      if (c.getFullMessage().indexOf(changeId) >= 0) {
        String lines[] = c.getFullMessage().trim().split("\n");
        String lastLine = lines.length > 0 ? lines[lines.length - 1] : "";

        if (lastLine.indexOf(changeId) == -1) {
          sb.append('\n');
          sb.append('\n');
          sb.append("Hint: A potential Change-Id was found, but it was not in the ");
          sb.append("footer (last paragraph) of the commit message.");
        }
      }
      sb.append('\n');
      sb.append('\n');
      sb.append("Hint: To automatically insert Change-Id, install the hook:\n");
      sb.append(getCommitMessageHookInstallationHint());
      sb.append('\n');
      sb.append("And then amend the commit:\n");
      sb.append("  git commit --amend\n");

      return new CommitValidationMessage(sb.toString(), false);
    }

    private String getCommitMessageHookInstallationHint() {
      if (installCommitMsgHookCommand != null) {
        return installCommitMsgHookCommand;
      }
      final List<HostKey> hostKeys = sshInfo.getHostKeys();

      // If there are no SSH keys, the commit-msg hook must be installed via
      // HTTP(S)
      if (hostKeys.isEmpty()) {
        String p = "${gitdir}/hooks/commit-msg";
        return String.format(
          "  gitdir=$(git rev-parse --git-dir); curl -o %s %s/tools/hooks/commit-msg ; chmod +x %s", p,
          getGerritUrl(canonicalWebUrl), p);
      }

      // SSH keys exist, so the hook can be installed with scp.
      String sshHost;
      int sshPort;
      String host = hostKeys.get(0).getHost();
      int c = host.lastIndexOf(':');
      if (0 <= c) {
        if (host.startsWith("*:")) {
          sshHost = getGerritHost(canonicalWebUrl);
        } else {
          sshHost = host.substring(0, c);
        }
        sshPort = Integer.parseInt(host.substring(c + 1));
      } else {
        sshHost = host;
        sshPort = 22;
      }

      return String.format("  gitdir=$(git rev-parse --git-dir); scp -p -P %d %s@%s:hooks/commit-msg ${gitdir}/hooks/",
          sshPort, user.getUserName(), sshHost);
    }
  }

  /**
   * If this is the special project configuration branch, validate the config.
   */
  public static class ConfigValidator implements CommitValidationListener {
    private final RefControl refControl;
    private final Repository repo;

    public ConfigValidator(RefControl refControl, Repository repo) {
      this.refControl = refControl;
      this.repo = repo;
    }

    @Override
    public List<CommitValidationMessage> onCommitReceived(
        CommitReceivedEvent receiveEvent) throws CommitValidationException {
      IdentifiedUser currentUser = (IdentifiedUser) refControl.getCurrentUser();

      if (REFS_CONFIG.equals(refControl.getRefName())) {
        List<CommitValidationMessage> messages = new LinkedList<>();

        try {
          ProjectConfig cfg =
              new ProjectConfig(receiveEvent.project.getNameKey());
          cfg.load(repo, receiveEvent.command.getNewId());
          if (!cfg.getValidationErrors().isEmpty()) {
            addError("Invalid project configuration:", messages);
            for (ValidationError err : cfg.getValidationErrors()) {
              addError("  " + err.getMessage(), messages);
            }
            throw new ConfigInvalidException("invalid project configuration");
          }
        } catch (Exception e) {
          log.error("User " + currentUser.getUserName()
              + " tried to push invalid project configuration "
              + receiveEvent.command.getNewId().name() + " for "
              + receiveEvent.project.getName(), e);
          throw new CommitValidationException("invalid project configuration",
              messages);
        }
      }
      return Collections.emptyList();
    }
  }

  /** Require permission to upload merges. */
  public static class UploadMergesPermissionValidator implements
      CommitValidationListener {
    private final RefControl refControl;

    public UploadMergesPermissionValidator(RefControl refControl) {
      this.refControl = refControl;
    }

    @Override
    public List<CommitValidationMessage> onCommitReceived(
        CommitReceivedEvent receiveEvent) throws CommitValidationException {
      if (receiveEvent.commit.getParentCount() > 1
          && !refControl.canUploadMerges()) {
        throw new CommitValidationException("you are not allowed to upload merges");
      }
      return Collections.emptyList();
    }
  }

  /** Execute commit validation plug-ins */
  public static class PluginCommitValidationListener implements
      CommitValidationListener {
    private final DynamicSet<CommitValidationListener> commitValidationListeners;

    public PluginCommitValidationListener(
        final DynamicSet<CommitValidationListener> commitValidationListeners) {
      this.commitValidationListeners = commitValidationListeners;
    }

    @Override
    public List<CommitValidationMessage> onCommitReceived(
        CommitReceivedEvent receiveEvent) throws CommitValidationException {
      List<CommitValidationMessage> messages = new LinkedList<>();

      for (CommitValidationListener validator : commitValidationListeners) {
        try {
          messages.addAll(validator.onCommitReceived(receiveEvent));
        } catch (CommitValidationException e) {
          messages.addAll(e.getMessages());
          throw new CommitValidationException(e.getMessage(), messages);
        }
      }
      return messages;
    }
  }

  public static class SignedOffByValidator implements CommitValidationListener {
    private final RefControl refControl;

    public SignedOffByValidator(RefControl refControl) {
      this.refControl = refControl;
    }

    @Override
    public List<CommitValidationMessage> onCommitReceived(
        CommitReceivedEvent receiveEvent) throws CommitValidationException {
      IdentifiedUser currentUser = (IdentifiedUser) refControl.getCurrentUser();
      final PersonIdent committer = receiveEvent.commit.getCommitterIdent();
      final PersonIdent author = receiveEvent.commit.getAuthorIdent();
      final ProjectControl projectControl = refControl.getProjectControl();

      if (projectControl.getProjectState().isUseSignedOffBy()) {
        boolean sboAuthor = false, sboCommitter = false, sboMe = false;
        for (final FooterLine footer : receiveEvent.commit.getFooterLines()) {
          if (footer.matches(FooterKey.SIGNED_OFF_BY)) {
            final String e = footer.getEmailAddress();
            if (e != null) {
              sboAuthor |= author.getEmailAddress().equals(e);
              sboCommitter |= committer.getEmailAddress().equals(e);
              sboMe |= currentUser.hasEmailAddress(e);
            }
          }
        }
        if (!sboAuthor && !sboCommitter && !sboMe
            && !refControl.canForgeCommitter()) {
          throw new CommitValidationException(
              "not Signed-off-by author/committer/uploader in commit message footer");
        }
      }
      return Collections.emptyList();
    }
  }

  /** Require that author matches the uploader. */
  public static class AuthorUploaderValidator implements
      CommitValidationListener {
    private final RefControl refControl;
    private final String canonicalWebUrl;

    public AuthorUploaderValidator(RefControl refControl, String canonicalWebUrl) {
      this.refControl = refControl;
      this.canonicalWebUrl = canonicalWebUrl;
    }

    @Override
    public List<CommitValidationMessage> onCommitReceived(
        CommitReceivedEvent receiveEvent) throws CommitValidationException {
      IdentifiedUser currentUser = (IdentifiedUser) refControl.getCurrentUser();
      final PersonIdent author = receiveEvent.commit.getAuthorIdent();

      if (!currentUser.hasEmailAddress(author.getEmailAddress())
          && !refControl.canForgeAuthor()) {
        List<CommitValidationMessage> messages = new LinkedList<>();

        messages.add(getInvalidEmailError(receiveEvent.commit, "author", author,
            currentUser, canonicalWebUrl));
        throw new CommitValidationException("invalid author", messages);
      }
      return Collections.emptyList();
    }
  }

  /** Require that committer matches the uploader. */
  public static class CommitterUploaderValidator implements
      CommitValidationListener {
    private final RefControl refControl;
    private final String canonicalWebUrl;

    public CommitterUploaderValidator(RefControl refControl,
        String canonicalWebUrl) {
      this.refControl = refControl;
      this.canonicalWebUrl = canonicalWebUrl;
    }

    @Override
    public List<CommitValidationMessage> onCommitReceived(
        CommitReceivedEvent receiveEvent) throws CommitValidationException {
      IdentifiedUser currentUser = (IdentifiedUser) refControl.getCurrentUser();
      final PersonIdent committer = receiveEvent.commit.getCommitterIdent();
      if (!currentUser.hasEmailAddress(committer.getEmailAddress())
          && !refControl.canForgeCommitter()) {
        List<CommitValidationMessage> messages = new LinkedList<>();
        messages.add(getInvalidEmailError(receiveEvent.commit, "committer", committer,
            currentUser, canonicalWebUrl));
        throw new CommitValidationException("invalid committer", messages);
      }
      return Collections.emptyList();
    }
  }

  /**
   * Don't allow the user to amend a merge created by Gerrit Code Review. This
   * seems to happen all too often, due to users not paying any attention to
   * what they are doing.
   */
  public static class AmendedGerritMergeCommitValidationListener implements
      CommitValidationListener {
    private final PersonIdent gerritIdent;
    private final RefControl refControl;

    public AmendedGerritMergeCommitValidationListener(
        final RefControl refControl, final PersonIdent gerritIdent) {
      this.refControl = refControl;
      this.gerritIdent = gerritIdent;
    }

    @Override
    public List<CommitValidationMessage> onCommitReceived(
        CommitReceivedEvent receiveEvent) throws CommitValidationException {
      final PersonIdent author = receiveEvent.commit.getAuthorIdent();

      if (receiveEvent.commit.getParentCount() > 1
          && author.getName().equals(gerritIdent.getName())
          && author.getEmailAddress().equals(gerritIdent.getEmailAddress())
          && !refControl.canForgeGerritServerIdentity()) {
        throw new CommitValidationException("do not amend merges not made by you");
      }
      return Collections.emptyList();
    }
  }

  /** Reject banned commits. */
  public static class BannedCommitsValidator implements
      CommitValidationListener {
    private final NoteMap rejectCommits;

    public BannedCommitsValidator(NoteMap rejectCommits) {
      this.rejectCommits = rejectCommits;
    }

    @Override
    public List<CommitValidationMessage> onCommitReceived(
        CommitReceivedEvent receiveEvent) throws CommitValidationException {
      try {
        if (rejectCommits.contains(receiveEvent.commit)) {
          throw new CommitValidationException("contains banned commit "
              + receiveEvent.commit.getName());
        }
        return Collections.emptyList();
      } catch (IOException e) {
        String m = "error checking banned commits";
        log.warn(m, e);
        throw new CommitValidationException(m, e);
      }
    }
  }

  /** Reject commits that don't pass user-supplied ref-update hook. */
  public static class ChangeHookValidator implements
      CommitValidationListener {
    private final RefControl refControl;
    private final ChangeHooks hooks;

    public ChangeHookValidator(RefControl refControl, ChangeHooks hooks) {
      this.refControl = refControl;
      this.hooks = hooks;
    }

    @Override
    public List<CommitValidationMessage> onCommitReceived(
        CommitReceivedEvent receiveEvent) throws CommitValidationException {

      if (refControl.getCurrentUser().isIdentifiedUser()) {
        IdentifiedUser user = (IdentifiedUser) refControl.getCurrentUser();

        String refname = receiveEvent.refName;
        ObjectId old = ObjectId.zeroId();
        if (receiveEvent.commit.getParentCount() > 0) {
          old = receiveEvent.commit.getParent(0);
        }
        if (receiveEvent.command.getRefName().startsWith(REFS_CHANGES)) {
          /*
           * If the ref-update hook tries to distinguish behavior between pushes to
           * refs/heads/... and refs/for/..., make sure we send it the correct refname.
           * Also, if this is targetting refs/for/, make sure we behave the same as
           * what a push to refs/for/ would behave; in particular, setting oldrev to
           * 0000000000000000000000000000000000000000.
           */
          refname = refname.replace(R_HEADS, "refs/for/refs/heads/");
          old = ObjectId.zeroId();
        }
        HookResult result = hooks.doRefUpdateHook(receiveEvent.project, refname,
            user.getAccount(), old, receiveEvent.commit);
        if (result != null && result.getExitValue() != 0) {
            throw new CommitValidationException(result.toString().trim());
        }
      }
      return Collections.emptyList();
    }
  }

  private static CommitValidationMessage getInvalidEmailError(RevCommit c, String type,
      PersonIdent who, IdentifiedUser currentUser, String canonicalWebUrl) {
    StringBuilder sb = new StringBuilder();
    sb.append("\n");
    sb.append("ERROR:  In commit ").append(c.name()).append("\n");
    sb.append("ERROR:  ").append(type).append(" email address ")
      .append(who.getEmailAddress()).append("\n");
    sb.append("ERROR:  does not match your user account.\n");
    sb.append("ERROR:\n");
    if (currentUser.getEmailAddresses().isEmpty()) {
      sb.append("ERROR:  You have not registered any email addresses.\n");
    } else {
      sb.append("ERROR:  The following addresses are currently registered:\n");
      for (String address : currentUser.getEmailAddresses()) {
        sb.append("ERROR:    ").append(address).append("\n");
      }
    }
    sb.append("ERROR:\n");
    if (canonicalWebUrl != null) {
      sb.append("ERROR:  To register an email address, please visit:\n");
      sb.append("ERROR:  ").append(canonicalWebUrl).append("#")
        .append(PageLinks.SETTINGS_CONTACT).append("\n");
    }
    sb.append("\n");
    return new CommitValidationMessage(sb.toString(), false);
  }

  /**
   * Get the Gerrit URL.
   *
   * @return the canonical URL (with any trailing slash removed) if it is
   *         configured, otherwise fall back to "http://hostname" where hostname
   *         is the value returned by {@link #getGerritHost(String)}.
   */
  private static String getGerritUrl(String canonicalWebUrl) {
    if (canonicalWebUrl != null) {
      return CharMatcher.is('/').trimTrailingFrom(canonicalWebUrl);
    } else {
      return "http://" + getGerritHost(canonicalWebUrl);
    }
  }

  /**
   * Get the Gerrit hostname.
   *
   * @return the hostname from the canonical URL if it is configured, otherwise
   *         whatever the OS says the hostname is.
   */
  private static String getGerritHost(String canonicalWebUrl) {
    String host;
    if (canonicalWebUrl != null) {
      try {
        host = new URL(canonicalWebUrl).getHost();
      } catch (MalformedURLException e) {
        host = SystemReader.getInstance().getHostname();
      }
    } else {
      host = SystemReader.getInstance().getHostname();
    }
    return host;
  }

  private static void addError(String error,
      List<CommitValidationMessage> messages) {
    messages.add(new CommitValidationMessage(error, true));
  }
}
