diff --git a/src/de/uni_passau/fim/seibt/gitwrapper/repo/Git.java b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Git.java new file mode 100644 index 0000000000000000000000000000000000000000..75fe15b4359f854133a72e31f15cf6d7c133ee8b --- /dev/null +++ b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Git.java @@ -0,0 +1,101 @@ +package de.uni_passau.fim.seibt.gitwrapper.repo; + +import java.io.File; +import java.io.IOException; +import java.util.Optional; +import java.util.Scanner; +import java.util.function.Function; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.io.IOUtils; + +public class Git { + + public static final int EXIT_SUCCESS = 0; + public static final int EXIT_FAIL = 1; + + private static final Logger LOG = Logger.getLogger(Git.class.getCanonicalName()); + private static final Pattern CLONING_INTO = Pattern.compile("Cloning into '(.*)'\\.\\.\\."); + + private class ExecRes { + private int code; + private String output; + } + + private String git; + + public Git(String git) { + this.git = git; + } + + public Optional<Repository> clone(File parentDir, String url) { + LOG.fine(() -> String.format("Cloning '%s'.", url)); + + Optional<ExecRes> res = exec(parentDir, "clone", url); + Function<ExecRes, Repository> toRepo = execRes -> { + + if (execRes.code != EXIT_SUCCESS) { + // the repo may already exist (resulting in code 128) - pull it? delete it? + LOG.warning(() -> String.format("Exit code %d indicates failure while cloning '%s'.", execRes.code, url)); + return null; + } + + Scanner sc = new Scanner(execRes.output); + + if (!sc.hasNextLine()) { + LOG.warning(() -> String.format("No output while cloning '%s'.", url)); + return null; + } + + Matcher matcher = CLONING_INTO.matcher(sc.nextLine()); + + if (!matcher.find()) { + LOG.warning(() -> String.format("Unexpected output while cloning '%s'", url)); + return null; + } + + String name = matcher.group(1); + File repoDir = new File(parentDir, name); + + LOG.fine(() -> "Cloned " + url + " into " + repoDir.getAbsolutePath()); + + return new Repository(this, url, repoDir); + }; + + return res.map(toRepo); + } + + public Optional<ExecRes> exec(File workingDirectory, String... parameters) { + ProcessBuilder b = new ProcessBuilder(); + String[] cmdArray = new String[parameters.length + 1]; + + cmdArray[0] = git; + System.arraycopy(parameters, 0, cmdArray, 1, parameters.length); + + b.command(cmdArray); + b.directory(workingDirectory); + b.redirectErrorStream(true); + + String cmd = String.join(" ", b.command()); + + LOG.fine(() -> String.format("Executing '%s'.", cmd)); + + try { + ExecRes res = new ExecRes(); + Process p = b.start(); + + res.output = IOUtils.toString(p.getInputStream()); + res.code = p.waitFor(); + + LOG.fine(() -> String.format("Execution of '%s' returned exit code %d.", cmd, res.code)); + + return Optional.of(res); + } catch (IOException | InterruptedException e) { + LOG.log(Level.SEVERE, e, () -> String.format("Exception executing '%s'.", cmd)); + return Optional.empty(); + } + } +} diff --git a/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java new file mode 100644 index 0000000000000000000000000000000000000000..4218b22346a6347f918fb3e22abafc1ae10e2fbf --- /dev/null +++ b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java @@ -0,0 +1,22 @@ +package de.uni_passau.fim.seibt.gitwrapper.repo; + +import java.io.File; + +public class Repository { + + private Git git; + + private String url; + private File dir; + + Repository(Git git, String url, File dir) { + this.git = git; + this.url = url; + this.dir = dir; + } + + @Override + public String toString() { + return String.format("Repository{url=%s, dir=%s}", url, dir); + } +}