From 862c4cac04094e6c1e9dad212413281c2843ee9a Mon Sep 17 00:00:00 2001
From: Georg Seibt <seibt@fim.uni-passau.de>
Date: Thu, 20 Oct 2016 10:07:45 +0200
Subject: [PATCH] doc of Repository methods and small refactorings to
 blameMergeConflicts (including renaming if to blameUnmergedFile)

---
 .../fim/seibt/gitwrapper/repo/BlameLine.java  |  2 +-
 .../seibt/gitwrapper/repo/MergeConflict.java  | 36 +++++++---
 .../fim/seibt/gitwrapper/repo/Repository.java | 72 +++++++++++++------
 3 files changed, 78 insertions(+), 32 deletions(-)

diff --git a/src/de/uni_passau/fim/seibt/gitwrapper/repo/BlameLine.java b/src/de/uni_passau/fim/seibt/gitwrapper/repo/BlameLine.java
index 682e622..18d260b 100644
--- a/src/de/uni_passau/fim/seibt/gitwrapper/repo/BlameLine.java
+++ b/src/de/uni_passau/fim/seibt/gitwrapper/repo/BlameLine.java
@@ -36,7 +36,7 @@ public class BlameLine {
     public final String line;
 
     /**
-     * Other (unrecognized) fields from the 'git blame' commit header.
+     * Other (unrecognized) fields from the 'git blame' commit header. Unmodifiable.
      */
     public final Map<String, String> otherHeaderFields;
 
diff --git a/src/de/uni_passau/fim/seibt/gitwrapper/repo/MergeConflict.java b/src/de/uni_passau/fim/seibt/gitwrapper/repo/MergeConflict.java
index bfd1342..a4ea900 100644
--- a/src/de/uni_passau/fim/seibt/gitwrapper/repo/MergeConflict.java
+++ b/src/de/uni_passau/fim/seibt/gitwrapper/repo/MergeConflict.java
@@ -1,21 +1,35 @@
 package de.uni_passau.fim.seibt.gitwrapper.repo;
 
+import java.nio.file.Path;
+import java.util.Collections;
 import java.util.List;
 
+/**
+ * A merge conflict parsed from the output of 'git blame' by {@link Repository#blameUnmergedFile(Path)} (String)}.
+ */
 public class MergeConflict {
-    private final List<BlameLine> left;
-    private final List<BlameLine> right;
 
-    public MergeConflict(List<BlameLine> left, List<BlameLine> right) {
-        this.left = left;
-        this.right = right;
-    }
+    /**
+     * The lines making up the left side of the conflict. Unmodifiable.
+     */
+    public final List<BlameLine> left;
 
-    public List<BlameLine> getLeft() {
-        return left;
-    }
+    /**
+     * The lines making up the right side of the conflict. Unmodifiable.
+     */
+    public final List<BlameLine> right;
 
-    public List<BlameLine> getRight() {
-        return right;
+    /**
+     * Constructs a new {@link MergeConflict}. The given lists {@code left} and {@code right} will be stored
+     * unmodifiable.
+     *
+     * @param left
+     *         the left lines of the conflict
+     * @param right
+     *         the right lines of the conflict
+     */
+    MergeConflict(List<BlameLine> left, List<BlameLine> right) {
+        this.left = Collections.unmodifiableList(left);
+        this.right = Collections.unmodifiableList(right);
     }
 }
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 731c74c..559f615 100644
--- a/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java
+++ b/src/de/uni_passau/fim/seibt/gitwrapper/repo/Repository.java
@@ -205,8 +205,8 @@ public class Repository {
     }
 
     /**
-     * Returns a {@link Commit} for the given ID. If the given ID does not designate a commit that exists in this
-     * {@link Repository} an empty {@link Optional} will be returned. The ID will be resolved to a full SHA1 hash.
+     * Optionally returns a {@link Commit} for the given ID. If the given ID does not designate a commit that exists in
+     * this {@link Repository}, an empty {@link Optional} will be returned. The ID will be resolved to a full SHA1 hash.
      *
      * @param id
      *         the ID of the commit
@@ -252,6 +252,14 @@ public class Repository {
         return catFile.map(toBoolean).orElse(false);
     }
 
+    /**
+     * Optionally returns a {@link Branch} for the given name. If the given name does not designated a branch that
+     * exists in this {@link Repository}, an empty {@link Optional} will be returned.
+     *
+     * @param name
+     *         the name of the branch
+     * @return the {@link Branch} or an empty {@link Optional} if the name is invalid or an exception occurs
+     */
     public Optional<Branch> getBranch(String name) {
         if (branches.containsKey(name)) {
             return Optional.of(branches.get(name));
@@ -348,10 +356,13 @@ public class Repository {
     }
 
     /**
-     * Creates a list of the lines of a file and their corresponding commit.
+     * Parses the output of 'git blame' for the given {@code file} and returns a list of {@link BlameLine BlameLines}
+     * containing the resulting information about every line of the file. If there is an exception parsing or obtaining
+     * the 'git blame' output, an empty {@link Optional} will be returned.
      *
-     * @param file the path to the file to analyze (relative to the git root or absolute)
-     * @return the list of {@link BlameLine BlameLines}
+     * @param file
+     *         the path to the file to analyze (relative to the git root or absolute)
+     * @return optionally the list of {@link BlameLine BlameLines}
      */
     public Optional<List<BlameLine>> blameFile(Path file) {
         Path path = dir.toPath().relativize(dir.toPath().resolve(file));
@@ -377,6 +388,14 @@ public class Repository {
         return output.map(toList);
     }
 
+    /**
+     * Parses the given 'git blame' output and returns a list of {@link BlameLine BlameLines} containing the resulting
+     * information about every line of the output.
+     *
+     * @param blameOutput
+     *         the 'git blame' output to parse
+     * @return the list of {@link BlameLine BlameLines}
+     */
     private List<BlameLine> parseBlameLines(String blameOutput) {
         Scanner lines = new Scanner(blameOutput);
 
@@ -479,13 +498,18 @@ public class Repository {
     }
 
     /**
-     * Gets a list of merge conflicts fo a file, as a pair of right side/left side of list of pairs of lines with their
-     * commits.
+     * Parses the output of 'git blame' for an unmerged file and extracts the merge conflicts that occurred in the file.
+     * Every merge conflict is represented by a {@link MergeConflict} instance containing the {@link BlameLine BlameLines}
+     * that represent the lines involved in the conflict. If there are no conflicts in the given file, an empty list
+     * will be returned. If there is an exception parsing or obtaining the 'git blame' output, an empty {@link Optional}
+     * will be returned.
      *
-     * @param file the file to analyze
-     * @return list of failed chunks
+     * @param file
+     *         the path to the unmerged file to analyze (relative to the git root or absolute)
+     * @return optionally the list of {@link MergeConflict MergeConflicts}
+     * @see #blameFile(Path)
      */
-    public Optional<List<MergeConflict>> blameMergeConflicts(Path file) {
+    public Optional<List<MergeConflict>> blameUnmergedFile(Path file) {
         Optional<List<BlameLine>> blame = blameFile(file);
 
         if (!blame.isPresent()) {
@@ -494,38 +518,46 @@ public class Repository {
 
         List<MergeConflict> conflicts = new ArrayList<>();
 
-        MergeConflict currentConflict = null;
+        List<BlameLine> left = null;
+        List<BlameLine> right = null;
         String lastMarker = null;
+
         for (BlameLine line : blame.get()) {
             if (line.line.startsWith(CONFLICT_START)) {
-                currentConflict = new MergeConflict(new ArrayList<>(), new ArrayList<>());
+                left = new ArrayList<>();
+                right = new ArrayList<>();
                 lastMarker = CONFLICT_START;
             } else if (line.line.startsWith(CONFLICT_MIDDLE)) {
                 lastMarker = CONFLICT_MIDDLE;
             } else if (line.line.startsWith(CONFLICT_END)) {
-                conflicts.add(currentConflict);
+                conflicts.add(new MergeConflict(left, right));
                 lastMarker = CONFLICT_END;
-            } else if (Objects.equals(lastMarker, CONFLICT_START)) {
-                //noinspection ConstantConditions: there is always a start marker before a relevant line.
-                currentConflict.getLeft().add(line);
-            } else if (Objects.equals(lastMarker, CONFLICT_MIDDLE)) {
-                //noinspection ConstantConditions: there is always a start marker before a relevant line.
-                currentConflict.getRight().add(line);
+            } else if (CONFLICT_START.equals(lastMarker)) {
+                assert left != null; left.add(line);
+            } else if (CONFLICT_MIDDLE.equals(lastMarker)) {
+                assert right != null; right.add(line);
             }
         }
 
         return Optional.of(conflicts);
     }
 
+    /**
+     * Parses and returns the current output of 'git status' for this {@link Repository}.
+     * If there is an exception parsing or obtaining the status output, an empty {@link Optional} will be returned.
+     *
+     * @return optionally the {@link Status} of this {@link Repository}
+     */
     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 Status.parseStatus(this, execRes.stdOut+"\0"); //TODO Parser so anpassen, dass kein \0 erforderlich ist.
         };
 
         return output.map(toStatus);
-- 
GitLab