import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import org.gradle.tooling.BuildException;
import org.gradle.tooling.BuildLauncher;
import org.gradle.tooling.GradleConnector;
import org.gradle.tooling.ProjectConnection;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.TreeFilter;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;

import com.google.common.io.ByteStreams;

@RunWith(Parameterized.class)
public class GradleBuildTest {    
  @Parameters(name="TestBuild{0}")
  public static Collection<String> data() {
      LinkedHashSet<String> projects = new LinkedHashSet<String>(); 
      try {
	  Repository repository = new FileRepositoryBuilder()
	      .readEnvironment() // scan environment GIT_* variables
	      .findGitDir() // scan up the file system tree
	      .build();
	  RevCommit head = new Git(repository)
	      .log().call()
	      .iterator().next();
	  TreeWalk treeWalk = new TreeWalk(repository);
	  treeWalk.addTree(head.getTree());
	  for (RevCommit p : head.getParents()) {
	      treeWalk.addTree(p.getTree());
	  }
	  treeWalk.setRecursive(false);
	  treeWalk.setFilter(TreeFilter.ANY_DIFF);
	  while (treeWalk.next()) {
	      File f = new File("../" + treeWalk.getPathString());
	      if (isProject(f)) {
		  System.err.println("project changed: " + f.getName());
		  projects.add(f.getName());
	      }
	  }
      } catch (java.io.IOException e) {
	  System.err.println("error opening git repository: " + e);
      } catch (GitAPIException e) {
	  System.err.println("error reading git repository log: " + e);
      }

      for (File p : new File("..").listFiles(new FileFilter() {
	      public boolean accept(File f) { return isProject(f); }
	  })) {
	  projects.add(p.getName());
      }
      return projects;
  }

  private static boolean isProject(File f) {
      return f.isDirectory() && Arrays.asList(f.list()).containsAll(Arrays.asList("build.gradle", "app"));
  }
    
  private File gradleProject;
  public GradleBuildTest(String projectDirectory) {
      this.gradleProject = new File("../" + projectDirectory);
  }

  @Test
  public void test() {
      GradleConnector connector = GradleConnector.newConnector();
      connector.forProjectDirectory(gradleProject);
      ProjectConnection connection = connector.connect();
      ByteArrayOutputStream stdout = new ByteArrayOutputStream();
      ByteArrayOutputStream stderr = new ByteArrayOutputStream();
      BuildLauncher launcher = connection.newBuild();
      launcher.setStandardOutput(stdout);
      launcher.setStandardError(stderr);
      try {
	  launcher.forTasks("app:lint");
	  launcher.run();

	  launcher.forTasks("build");
	  launcher.run();
      } catch (BuildException e) {
	  try {
	      String lintReportPath = gradleProject.getPath() +  "/app/build/outputs/lint-results.html";	      
	      Process p = new ProcessBuilder("pandoc",
					     lintReportPath,
					     "-t",
					     "plain").redirectErrorStream(true).start();
	      p.waitFor();
	      fail(String.format("BUILD FAILED: %s\nSTDOUT: %s\nSTDERR: %s\nLINT: %s",
				 e, stdout, stderr, new String(ByteStreams.toByteArray(p.getInputStream()))));
	  } catch (Exception pe) {
	      fail(String.format("failed to get lint report: %s", pe.toString()));
	  }
      } finally {
	  connection.close();
      }
  }
}

@@ -341,24 +341,115 @@
 tConnection;
+%0Aimport org.gradle.tooling.model.GradleProject;%0Aimport org.gradle.tooling.model.GradleTask;
 %0A%0Aimport org
@@ -2901,24 +2901,227 @@
 .connect();%0A
+      GradleProject project = connection.getModel(GradleProject.class);%0A      for(GradleTask task : project.getChildren().getAt(0).getTasks()) %7B%0A%09  System.err.println(%22task: %22 + task.getName());%0A      %7D%0A
       ByteAr
@@ -3442,17 +3442,16 @@
 .run();%0A
-%0A
 %09  launc
@@ -3464,21 +3464,89 @@
 rTasks(%22
-build
+assembleDebug%22);%0A%09  launcher.run();%0A%09  launcher.forTasks(%22assembleRelease
 %22);%0A%09  l
@@ -3559,16 +3559,19 @@
 r.run();
+%09  
 %0A      %7D

use assemble instead of build and print tasks