// 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.entities.Project;
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.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 = 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();
  }
}
