package com.github.blindpirate.gogradle.util;


import com.google.common.collect.Lists;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

public class ProcessUtils {
    public static class ProcessResult {
        private int code;
        private String stdout;
        private String stderr;

        public int getCode() {
            return code;
        }

        public String getStdout() {
            return stdout;
        }

        public String getStderr() {
            return stderr;
        }

        public ProcessResult(Process process) throws InterruptedException {
            code = process.waitFor();
            stdout = IOUtils.toString(process.getInputStream());
            stderr = IOUtils.toString(process.getErrorStream());
        }
    }

    public static ProcessResult run(List<String> args, Map<String, String> envs) {
        return run(args, envs, null);
    }

    public static ProcessResult run(List<String> args, Map<String, String> envs, File workingDirectory) {
        try {
            ProcessBuilder pb = new ProcessBuilder().command(args);
            pb.environment().putAll(envs);
            if (workingDirectory != null) {
                pb.directory(workingDirectory);
            }
            Process process = pb.start();
            return new ProcessResult(process);
        } catch (IOException | InterruptedException e) {
            throw ExceptionHandler.uncheckException(e);
        }
    }


    public static ProcessResult runProcessWithCurrentClasspath(Class mainClass,
                                                               List<String> args,
                                                               Map<String, String> envs) {
        String currentClasspath = System.getProperty("java.class.path");

        List<String> cmds = Lists.newArrayList("java", "-cp", currentClasspath, mainClass.getName());
        cmds.addAll(args);
        return run(cmds, envs);
    }
}

@@ -131,16 +131,41 @@
 eption;%0A
+import java.util.Arrays;%0A
 import j
@@ -230,16 +230,102 @@
 Utils %7B%0A
+    private static final ProcessUtilsDelegate DELEGATE = new ProcessUtilsDelegate();%0A%0A
     publ
@@ -957,54 +957,132 @@
 ult 
-run(List%3CString%3E args, Map%3CString, String%3E env
+getResult(Process process) %7B%0A        return DELEGATE.getResult(process);%0A%0A    %7D%0A%0A    public static Process run(String... arg
 s) %7B
@@ -1105,18 +1105,33 @@
 run(
+Arrays.asList(
 args
+)
 , 
-envs
+null
 , nu
@@ -1163,30 +1163,24 @@
 atic Process
-Result
  run(List%3CSt
@@ -1219,485 +1219,223 @@
 envs
-, File workingDirectory) %7B%0A        try %7B%0A            ProcessBuilder pb = new ProcessBuilder().command(args);%0A            pb.environment().putAll(envs
+) %7B%0A        return run(args, envs, null
 );%0A    
+%7D%0A%0A
     
-    if (workingDirectory != null) %7B%0A                pb.directory(workingDirectory);%0A            %7D%0A            Process process = pb.start();%0A            return new ProcessResult(process);%0A        %7D catch (IOException %7C InterruptedException e) %7B%0A            throw ExceptionHandler.uncheckException(e);%0A        %7D
+public static Process run(List%3CString%3E args, Map%3CString, String%3E envs, File workingDirectory) %7B%0A        return DELEGATE.run(args, envs, workingDirectory);
 %0A    %7D%0A%0A
 %0A   
@@ -1430,17 +1430,16 @@
 %0A    %7D%0A%0A
-%0A
     publ
@@ -1675,32 +1675,1337 @@
 String%3E envs) %7B%0A
+        return DELEGATE.runProcessWithCurrentClasspath(mainClass, args, envs);%0A    %7D%0A%0A    public static class ProcessUtilsDelegate %7B%0A        private ProcessUtilsDelegate() %7B%0A        %7D%0A%0A        ProcessResult getResult(Process process) %7B%0A            try %7B%0A                return new ProcessResult(process);%0A            %7D catch (InterruptedException e) %7B%0A                throw ExceptionHandler.uncheckException(e);%0A            %7D%0A        %7D%0A%0A        Process run(List%3CString%3E args, Map%3CString, String%3E envs, File workingDirectory) %7B%0A            try %7B%0A                ProcessBuilder pb = new ProcessBuilder().command(args);%0A                if (envs != null) %7B%0A                    pb.environment().putAll(envs);%0A                %7D%0A                if (workingDirectory != null) %7B%0A                    pb.directory(workingDirectory);%0A                %7D%0A                return pb.start();%0A            %7D catch (IOException e) %7B%0A                throw ExceptionHandler.uncheckException(e);%0A            %7D%0A        %7D%0A%0A        // this should be moved to test source set since it's only used in test%0A        ProcessResult runProcessWithCurrentClasspath(Class mainClass,%0A                                                     List%3CString%3E args,%0A                                                     Map%3CString, String%3E envs) %7B%0A    
         String c
@@ -3058,24 +3058,28 @@
 ss.path%22);%0A%0A
+    
         List
@@ -3176,16 +3176,20 @@
         
+    
 cmds.add
@@ -3203,31 +3203,45 @@
 s);%0A        
+    
 return 
+getResult(
 run(cmds, en
@@ -3238,23 +3238,40 @@
 n(cmds, envs
-);
+, null));%0A        %7D
 %0A    %7D%0A%7D%0A

Refactor ProcessUtils to allow mock