/*
 * Copyright (C) 2016 Google 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.google.copybara.git;

import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.google.common.base.Preconditions;
import com.google.copybara.GeneralOptions;
import com.google.copybara.Option;
import com.google.copybara.RepoException;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Supplier;
import javax.annotation.Nullable;

/**
 * Common arguments for {@link GitDestination}, {@link GitOrigin}, and other Git components.
 */
@Parameters(separators = "=")
public class GitOptions implements Option {

  private final Supplier<GeneralOptions> generalOptionsSupplier;

  // Not used by git.destination but it will be at some point to make fetches more efficient.
  @Parameter(names = "--git-repo-storage",
      description = "Location of the storage path for git repositories. DEPRECATED",
      // TODO(malcon): Deprecate this flag
      hidden = true)
  String repoStorage;

  @Parameter(names = "--git-credential-helper-store-file",
      description = "Credentials store file to be used. See "
          + "https://git-scm.com/docs/git-credential-store")
  String credentialHelperStorePath;

  public GitOptions(Supplier<GeneralOptions> generalOptionsSupplier) {
    this(generalOptionsSupplier, /*credentialHelperStorePath=*/null);
  }

  /** Used internally to customize the path for credential store. */
  @SuppressWarnings("unused")
  public GitOptions(Supplier<GeneralOptions> generalOptionsSupplier,
      @Nullable String defaultCredentialHelperStorePath) {
    this.generalOptionsSupplier = Preconditions.checkNotNull(generalOptionsSupplier);
    this.credentialHelperStorePath = defaultCredentialHelperStorePath;
  }

  private Path getRepoStorage() throws IOException {
    if (repoStorage == null) {
      return generalOptionsSupplier.get().getDirFactory().getCacheDir("git_repos");
    }
    return Paths.get(repoStorage);
  }

  public final GitRepository cachedBareRepoForUrl(String url) throws RepoException {
    Preconditions.checkNotNull(url);
    try {
      return createBareRepo(generalOptionsSupplier.get(),
          GitRepository.createGitDirInCache(url, getRepoStorage()));
    } catch (IOException e) {
      throw new RepoException("Cannot create a cached repo for " + url, e);
    }
  }

  /**
   * Create a new initialized repository in the location.
   *
   * <p>Can be overwritten to create custom GitRepository objects.
   */
  protected GitRepository createBareRepo(GeneralOptions generalOptions, Path path)
      throws RepoException {
    GitRepository repo = GitRepository.newBareRepo(path, generalOptions.getEnvironment(),
        generalOptions.isVerbose());
    return initRepo(repo);
  }

  protected GitRepository initRepo(GitRepository repo) throws RepoException {
    String path = credentialHelperStorePath == null ? "" : " --file=" + credentialHelperStorePath;
    return repo.init().withCredentialHelper("store" + path);
  }
}

@@ -1572,16 +1572,120 @@
 orage;%0A%0A
+  @Nullable%0A  public String getCredentialHelperStorePath() %7B%0A    return credentialHelperStorePath;%0A  %7D%0A%0A
   @Param
@@ -1901,250 +1901,226 @@
 %0A%0A  
-public GitOptions(Supplier%3CGeneralOptions%3E generalOptionsSupplier) %7B%0A    this(generalOptionsSupplier, /*credentialHelperStorePath=*/null);%0A  %7D%0A%0A  /** Used internally to customize the path for credential store. */%0A  @SuppressWarnings(%22unused%22)
+@Parameter(names = %22--nogit-credential-helper-store%22,%0A      description = %22Disable using credentials store. See %22%0A          + %22https://git-scm.com/docs/git-credential-store%22)%0A  boolean noCredentialHelperStore = false;%0A
 %0A  p
@@ -2187,65 +2187,8 @@
 lier
-,%0A      @Nullable String defaultCredentialHelperStorePath
 ) %7B%0A
@@ -2277,79 +2277,8 @@
 r);%0A
-    this.credentialHelperStorePath = defaultCredentialHelperStorePath;%0A
   %7D%0A
@@ -2678,24 +2678,42 @@
 lier.get(),%0A
+                  
           Gi
@@ -3226,24 +3226,67 @@
 ironment(),%0A
+                                           
         gene
@@ -3416,24 +3416,101 @@
 Exception %7B%0A
+    repo.init();%0A    if (noCredentialHelperStore) %7B%0A      return repo;%0A    %7D%0A
     String p
@@ -3512,16 +3512,24 @@
 ing 
-p
+storeP
 ath = 
-c
+getC
 rede
@@ -3552,86 +3552,87 @@
 Path
- == null ? %22%22 : %22 --file=%22 + credentialHelperStorePath;%0A    return repo.init()
+();%0A    String path = storePath == null ? %22%22 : %22 --file=%22 + storePath;%0A    repo
 .wit
@@ -3666,14 +3666,31 @@
  path);%0A
+    return repo;%0A
   %7D%0A%7D%0A

Make git options credentials store more extensible