From 9e73661900b28a0db950a807fc9203499d6530d1 Mon Sep 17 00:00:00 2001
From: Florian Heck <florian.heck@hotmail.de>
Date: Tue, 18 Oct 2016 17:40:43 +0200
Subject: [PATCH] added status bean and method for parsing status

---
 .../fim/seibt/gitwrapper/repo/Repository.java | 14 ++++
 .../fim/seibt/gitwrapper/repo/Status.java     | 67 +++++++++++++++++++
 2 files changed, 81 insertions(+)
 create mode 100644 src/de/uni_passau/fim/seibt/gitwrapper/repo/Status.java

diff --git a/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java
index 0f8bbd9..1f66e8d 100644
--- a/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java
+++ b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java
@@ -452,6 +452,20 @@ public class Repository {
         return Optional.of(conflicts);
     }
 
+    public Optional<Status> getStatus() {
+        Optional<ExecRes> output = git.exec(dir, "status", "-z");
+        Function<ExecRes, Status> toStatus = execRes -> {
+            if (git.failed(execRes)) {
+                LOG.warning(() -> String.format("Failed to get status information for repo %s", this));
+                return null;
+            }
+
+            return Status.parseStatus(this, execRes.stdOut+"\0");
+        };
+
+        return output.map(toStatus);
+    }
+
     /**
      * Returns the {@link GitWrapper} used by this {@link Repository}.
      *
diff --git a/src/de/uni_passau/fim/seibt/gitwrapper/repo/Status.java b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Status.java
new file mode 100644
index 0000000..8cb4112
--- /dev/null
+++ b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Status.java
@@ -0,0 +1,67 @@
+package de.uni_passau.fim.seibt.gitwrapper.repo;
+
+import java.io.File;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Status {
+    private static final Pattern STATUS_ENTRY = Pattern.compile("(.?.) (?:.*? )?(.*?)\0");
+
+    public final String head;
+    public final Map<File, String> changed;
+    public final Map<File, String> unmerged;
+
+    private Status(String head, Map<File, String> changed, Map<File, String> unmerged) {
+        this.head = head;
+        this.changed = Collections.unmodifiableMap(changed);
+        this.unmerged = Collections.unmodifiableMap(unmerged);
+    }
+
+    public boolean isClean() {
+        return changed.isEmpty() && unmerged.isEmpty();
+    }
+
+    public boolean hasConflicts() {
+        return !unmerged.isEmpty();
+    }
+
+    @Override
+    public String toString() {
+        String out = "";
+        if (isClean()) {
+            out = "Clean working directory on commit " + head + "\n";
+        } else {
+            if (!unmerged.isEmpty()) {
+                out = "Unmerged files:";
+                out += unmerged.keySet().stream().map(File::getPath).reduce("", (list, file) -> String.join("\n", list, file));
+                out += "\n";
+            }
+            if (!changed.isEmpty()) {
+                out += "Changed files:";
+                out += changed.keySet().stream().map(File::getPath).reduce("", (list, file) -> String.join("\n", list, file));
+                out += "\n";
+            }
+        }
+
+        return out;
+    }
+
+    static Status parseStatus(Repository repo, String gitOutput) {
+        Map<File, String> changed = new HashMap<>();
+        Map<File, String> unmerged = new HashMap<>();
+        Matcher matcher = STATUS_ENTRY.matcher(gitOutput);
+        while (matcher.find()) {
+            // used new path, if file was moved
+            File file = new File(matcher.group(2));
+            String code = matcher.group(1).toUpperCase();
+            if (code.contains("U")) {
+                unmerged.put(file, code);
+            } else {
+                changed.put(file, code);
+            }
+        }
+
+        return new Status(repo.getCurrentHEAD().get().getId(), changed, unmerged);
+    }
+}
-- 
GitLab