/*
 * Copyright 2017 the original author or authors.
 *
 * 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 org.gradle.vcs.git.internal;

import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.gradle.api.GradleException;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.vcs.VersionControlSpec;
import org.gradle.vcs.VersionControlSystem;
import org.gradle.vcs.git.GitVersionControlSpec;

import java.io.File;
import java.io.IOException;
import java.net.URI;

/**
 * A Git {@link VersionControlSystem} implementation.
 */
public class GitVersionControlSystem implements VersionControlSystem {
    private static final Logger LOGGER = Logging.getLogger(GitVersionControlSystem.class);
    @Override
    public void populate(File workingDir, VersionControlSpec spec) {
        if (!(spec instanceof GitVersionControlSpec)) {
            throw new IllegalArgumentException("The GitVersionControlSystem can only handle GitVersionConrolSpec instances.");
        }
        GitVersionControlSpec gitSpec = (GitVersionControlSpec) spec;

        File dbDir = new File(workingDir, ".git");
        if (dbDir.exists() && dbDir.isDirectory()) {
            updateRepo(workingDir, gitSpec);
        } else {
            cloneRepo(workingDir, gitSpec);
        }
    }

    private void cloneRepo(File workingDir, GitVersionControlSpec gitSpec) {
        CloneCommand clone = Git.cloneRepository().setURI(gitSpec.getUrl().toString()).setDirectory(workingDir);
        Git git = null;
        try {
            git = clone.call();
        } catch (GitAPIException e) {
            throw wrapGitCommandException("clone", gitSpec.getUrl(), workingDir, e);
        } catch (JGitInternalException e) {
            throw wrapGitCommandException("clone", gitSpec.getUrl(), workingDir, e);
        } finally {
            if (git != null) {
                git.close();
            }
        }
    }

    private void updateRepo(File workingDir, GitVersionControlSpec gitSpec) {
        Git git = null;
        try {
            git = Git.open(workingDir);
            git.pull().setRemote(gitSpec.getUrl().toString()).call();
        } catch (IOException e) {
            throw wrapGitCommandException("update", gitSpec.getUrl(), workingDir, e);
        } catch (GitAPIException e) {
            throw wrapGitCommandException("update", gitSpec.getUrl(), workingDir, e);
        } catch (JGitInternalException e) {
            throw wrapGitCommandException("update", gitSpec.getUrl(), workingDir, e);
        } finally {
            if (git != null) {
                git.close();
            }
        }
    }

    private GradleException wrapGitCommandException(String commandName, URI repoUrl, File workingDir, Exception e) {
        return new GradleException(String.format("Could not {}: {} from {}", commandName, repoUrl, workingDir), e);
    }
}

@@ -825,32 +825,108 @@
 ernalException;%0A
+import org.eclipse.jgit.lib.Config;%0Aimport org.eclipse.jgit.lib.Repository;%0A
 import org.gradl
@@ -940,32 +940,32 @@
 radleException;%0A
-
 import org.gradl
@@ -1230,16 +1230,64 @@
 net.URI;
+%0Aimport java.util.HashSet;%0Aimport java.util.Set;
 %0A%0A/**%0A *
@@ -2890,16 +2890,53 @@
 tRemote(
+getRemoteForUrl(git.getRepository(), 
 gitSpec.
@@ -2943,26 +2943,16 @@
 getUrl()
-.toString(
 )).call(
@@ -3431,32 +3431,1065 @@
        %7D%0A    %7D%0A%0A
+    private String getRemoteForUrl(Repository repository, URI url) %7B%0A        Config config = repository.getConfig();%0A        Set%3CString%3E remotes = config.getSubsections(%22remote%22);%0A        Set%3CString%3E foundUrls = new HashSet%3CString%3E();%0A%0A        for (String remote : remotes) %7B%0A            String remoteUrl = config.getString(%22remote%22, remote, %22url%22);%0A            if (remoteUrl.equals(safeRepositoryUrl(url))) %7B%0A                return remote;%0A            %7D else %7B%0A                foundUrls.add(remoteUrl);%0A            %7D%0A        %7D%0A        throw new GradleException(String.format(%22Could not find remote with url: %25s. Found: %25s%22, url, foundUrls));%0A    %7D%0A%0A    // This is a horrible hack to work around a bug in how jgit stores and expects file urls for remotes.%0A    private String safeRepositoryUrl(URI url) %7B%0A        String urlString = url.toString();%0A        if (urlString.startsWith(%22file:/%22) && !urlString.startsWith(%22file:///%22)) %7B%0A            return urlString.replace(%22file:/%22, %22file:///%22);%0A        %7D%0A        return urlString;%0A    %7D%0A%0A
     private Grad
@@ -4653,22 +4653,22 @@
 not 
-%7B%7D: %7B%7D
+%25s: %25s
  from 
-%7B%7D
+%25s
 %22, c

Fix failing test