Skip to content
Snippets Groups Projects
Commit 862c4cac authored by Georg Seibt's avatar Georg Seibt :nerd:
Browse files

doc of Repository methods and small refactorings to blameMergeConflicts...

doc of Repository methods and small refactorings to blameMergeConflicts (including renaming if to blameUnmergedFile)
parent db6601f1
No related branches found
No related tags found
No related merge requests found
......@@ -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;
......
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);
}
}
......@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment