// Copyright (C) 2020 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.integration.git;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.PushOneCommit.FILE_CONTENT;
import static com.google.gerrit.acceptance.PushOneCommit.FILE_NAME;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.acceptance.GerritConfig;
import com.google.gerrit.acceptance.GerritServer.TestSshServerAddress;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.StandaloneSiteTest;
import com.google.gerrit.acceptance.UseSsh;
import com.google.gerrit.common.RawInputUtil;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.common.ChangeInput;
import com.google.gerrit.extensions.common.CommitInfo;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Project;
import com.google.inject.Inject;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
import org.junit.Test;

@NoHttpd
@UseSsh
public class UploadArchiveIT extends StandaloneSiteTest {
  private static final String[] SSH_KEYGEN_CMD =
      new String[] {"ssh-keygen", "-t", "rsa", "-q", "-P", "", "-f"};
  private static final String GIT_SSH_COMMAND =
      "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o 'IdentitiesOnly yes' -i";
  private static final String ARCHIVE = "archive";

  @Inject private GerritApi gApi;
  @Inject private @TestSshServerAddress InetSocketAddress sshAddress;

  private String sshDestination;
  private String identityPath;
  private Project.NameKey project;
  private CommitInfo commit;

  @Test
  @GerritConfig(name = "download.archive", value = "off")
  public void archiveFeatureOff() throws Exception {
    try (ServerContext ctx = startServer()) {
      setUpTestHarness(ctx);
      assertArchiveNotPermitted();
    }
  }

  @Test
  @GerritConfig(
      name = "download.archive",
      values = {"tar", "tbz2", "tgz", "txz"})
  public void zipFormatDisabled() throws Exception {
    try (ServerContext ctx = startServer()) {
      setUpTestHarness(ctx);
      assertArchiveNotPermitted();
    }
  }

  @Test
  public void verifyUploadArchiveFormats() throws Exception {
    try (ServerContext ctx = startServer()) {
      setUpTestHarness(ctx);
      setUpChange();
      for (String f : Arrays.asList("zip", "tar", "tar.gz", "tar.bz2", "tar.xz")) {
        verifyUploadArchive(f);
      }
    }
  }

  private void verifyUploadArchive(String format) throws Exception {
    Path outputPath = sitePaths.data_dir.resolve(ARCHIVE);
    execute(
        cmd(format, commit.commit),
        sitePaths.data_dir.toFile(),
        ImmutableMap.of("GIT_SSH_COMMAND", GIT_SSH_COMMAND + identityPath),
        outputPath);
    try (InputStream fi = Files.newInputStream(outputPath);
        InputStream bi = new BufferedInputStream(fi);
        ArchiveInputStream archive = archiveStreamForFormat(bi, format)) {
      assertEntries(archive);
    }
  }

  private ArchiveInputStream archiveStreamForFormat(InputStream bi, String format)
      throws IOException {
    switch (format) {
      case "zip":
        return new ZipArchiveInputStream(bi);
      case "tar":
        return new TarArchiveInputStream(bi);
      case "tar.gz":
        return new TarArchiveInputStream(new GzipCompressorInputStream(bi));
      case "tar.bz2":
        return new TarArchiveInputStream(new BZip2CompressorInputStream(bi));
      case "tar.xz":
        return new TarArchiveInputStream(new XZCompressorInputStream(bi));
      default:
        throw new IllegalArgumentException("Unknown archive format: " + format);
    }
  }

  private void setUpTestHarness(ServerContext ctx) throws RestApiException, Exception {
    ctx.getInjector().injectMembers(this);
    project = new Project.NameKey("upload-archive-project-test");
    gApi.projects().create(project.get());
    setUpAuthentication();
    sshDestination =
        String.format(
            "ssh://%s@%s:%s/%s",
            "admin", sshAddress.getHostName(), sshAddress.getPort(), project.get());
    identityPath = sitePaths.data_dir.resolve(String.format("id_rsa_%s", "admin")).toString();
  }

  private void setUpAuthentication() throws Exception {
    execute(
        ImmutableList.<String>builder()
            .add(SSH_KEYGEN_CMD)
            .add(String.format("id_rsa_%s", "admin"))
            .build());
    gApi.accounts()
        .id("admin")
        .addSshKey(
            new String(
                java.nio.file.Files.readAllBytes(
                    sitePaths.data_dir.resolve(String.format("id_rsa_%s.pub", "admin"))),
                UTF_8));
  }

  private ImmutableList<String> cmd(String format, String commit) {
    return ImmutableList.<String>builder()
        .add("git")
        .add("archive")
        .add("-f=" + format)
        .add("--prefix=" + commit + "/")
        .add("--remote=" + sshDestination)
        .add(commit)
        .add(FILE_NAME)
        .build();
  }

  private String execute(ImmutableList<String> cmd) throws Exception {
    return execute(cmd, sitePaths.data_dir.toFile(), ImmutableMap.of());
  }

  private void assertArchiveNotPermitted() {
    IOException exception =
        assertThrows(
            IOException.class,
            () ->
                execute(
                    cmd("zip", "master"),
                    sitePaths.data_dir.toFile(),
                    ImmutableMap.of("GIT_SSH_COMMAND", GIT_SSH_COMMAND + identityPath)));
    assertThat(exception)
        .hasMessageThat()
        .contains("fatal: upload-archive not permitted for format zip");
  }

  private void setUpChange() throws Exception {
    ChangeInput in = new ChangeInput(project.get(), "master", "Test change");
    in.newBranch = true;
    String changeId = gApi.changes().create(in).info().changeId;
    gApi.changes().id(changeId).edit().modifyFile(FILE_NAME, RawInputUtil.create(FILE_CONTENT));
    gApi.changes().id(changeId).edit().publish();
    commit = gApi.changes().id(changeId).current().commit(false);
  }

  private void assertEntries(ArchiveInputStream o) throws IOException {
    Set<String> entryNames = new TreeSet<>();
    ArchiveEntry e;
    while ((e = o.getNextEntry()) != null) {
      entryNames.add(e.getName());
    }
    assertThat(entryNames)
        .containsExactly(
            String.format("%s/", commit.commit), String.format("%s/%s", commit.commit, FILE_NAME))
        .inOrder();
  }
}
