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