package org.jenkinsci.plugins.gitclient;

import hudson.EnvVars;
import hudson.FilePath;
import hudson.FilePath.FileCallable;
import hudson.model.TaskListener;
import hudson.plugins.git.GitAPI;
import hudson.remoting.VirtualChannel;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;

/**
 * @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
 */
public class Git implements Serializable {
    private FilePath repository;
    private TaskListener listener;
    private EnvVars env;
    private String exe;

    public Git(TaskListener listener, EnvVars env) {
        this.listener = listener;
        this.env = env;
    }

    public static Git with(TaskListener listener, EnvVars env) {
        return new Git(listener, env);
    }

    public Git in(File repository) {
        return in(new FilePath(repository));
    }

    public Git in(FilePath repository) {
        this.repository = repository;
        return this;
    }

    /**
     * Set the (node/environment specific) git executable to be used
     * If not set, JGit implementation will be used, assuming you don't rely on unimplemented CLI methods
     */
    public Git using(String exe) {
        this.exe = exe;
        return this;
    }

    public GitClient getClient() throws IOException, InterruptedException {
        return repository.act(new FileCallable<GitClient>() {
            public GitClient invoke(File f, VirtualChannel channel) throws IOException, InterruptedException {
                if (listener == null) listener = TaskListener.NULL;
                if (env == null) env = new EnvVars();

                if (exe == null || "jgit".equalsIgnoreCase(exe)) {
                    return new JGitAPIImpl(f, listener);
                }
                // Ensure we return a backward compatible GitAPI, even API only claim to provide a GitClient
                return new GitAPI(exe, f, listener, env);
            }
        });
    }

    // Can be use to force use of the 100% backward-compatible CLI GitClient
    public static boolean USE_CLI = Boolean.valueOf(System.getProperty(Git.class.getName() + ".useCLI", "true"));

    private static final long serialVersionUID = 1L;
}

@@ -227,16 +227,50 @@
 annel;%0A%0A
+import javax.annotation.Nullable;%0A
 import j
@@ -278,24 +278,24 @@
 va.io.File;%0A
-
 import java.
@@ -464,16 +464,30 @@
 zable %7B%0A
+    @Nullable%0A
     priv
@@ -1387,30 +1387,43 @@
     
-return repository.act(
+FileCallable%3CGitClient%3E callable = 
 new 
@@ -1999,32 +1999,32 @@
 ;%0A            %7D%0A
-
         %7D);%0A    
@@ -2016,16 +2016,104 @@
        %7D
+;%0A        return repository!=null ? repository.act(callable) : callable.invoke(null,null
 );%0A    %7D

repository can be null