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

Implement more extensive Status parsing. Regex is not working yet...

parent e3f182df
No related branches found
No related tags found
No related merge requests found
......@@ -9,6 +9,12 @@ import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static de.uni_passau.fim.seibt.gitwrapper.repo.Status.StatusCode.ADDED;
import static de.uni_passau.fim.seibt.gitwrapper.repo.Status.StatusCode.DELETED;
import static de.uni_passau.fim.seibt.gitwrapper.repo.Status.StatusCode.IGNORED;
import static de.uni_passau.fim.seibt.gitwrapper.repo.Status.StatusCode.UNMERGED;
import static de.uni_passau.fim.seibt.gitwrapper.repo.Status.StatusCode.UNTRACKED;
/**
* The status of a {@link Repository}.
*
......@@ -16,7 +22,105 @@ import java.util.regex.Pattern;
*/
public class Status {
private static final Pattern STATUS_ENTRY = Pattern.compile("(.?.) (?:.*? )?(.*?)\0");
private static final Pattern STATUS_ENTRY = Pattern.compile("(..) ([^\0]*)\0(?:([^\0 ]*)\0)?");
/**
* Two {@link StatusCode StatusCodes} are used to represent the status of a file in a git {@link Repository}.
*
* @see <a href=https://git-scm.com/docs/git-status>The Documentation of 'git status'</a>
*/
public enum StatusCode {
UNMODIFIED,
MODIFIED,
ADDED,
DELETED,
RENAMED,
COPIED,
/**
* Updated but unmerged.
*/
UNMERGED,
UNTRACKED,
IGNORED;
/**
* Returns the enum constant representing the given status code character. Must be one of ' ', 'M', 'A', 'D',
* 'R', 'C', 'U', '?', '!'.
*
* @param c
* the status character
* @return the corresponding enum constant
* @throws IllegalArgumentException
* if there is no enum constant for the given character
* @see <a href=https://git-scm.com/docs/git-status>The Documentation of 'git status'</a>
*/
private static StatusCode forChar(char c) {
switch (c) {
case ' ':
return UNMODIFIED;
case 'M':
return MODIFIED;
case 'A':
return ADDED;
case 'D':
return DELETED;
case 'R':
return RENAMED;
case 'C':
return COPIED;
case 'U':
return UNMERGED;
case '?':
return UNTRACKED;
case '!':
return IGNORED;
default:
throw new IllegalArgumentException("No enum constant for status code '" + c + "'.");
}
}
}
/**
* Represents the status of a file in a git {@link Repository}. For files with merge conflicts, {@link #x} and
* {@link #y} show the modification states of each side of the merge. For files that do not have merge conflicts,
* {@link #x} shows the status of the index, and {@link #y} shows the status of the work tree.
*/
public static class FileStatus {
/**
* The first status code.
*/
public final StatusCode x;
/**
* The second status code.
*/
public final StatusCode y;
/**
* In case of renamings this path represents the filename before the renaming.
*/
public final Optional<Path> oldFile;
/**
* The file whose status is represented by this {@link FileStatus} instance.
*/
public final Path file;
private FileStatus(StatusCode x, StatusCode y, Optional<Path> oldFile, Path file) {
if ((x == UNTRACKED ^ y == UNTRACKED) || (x == IGNORED ^ y == IGNORED)) {
throw new IllegalArgumentException("If one of the two status codes is UNTRACKED or IGNORED, the other must be the same.");
}
this.x = x;
this.y = y;
this.oldFile = oldFile;
this.file = file;
}
}
/**
* The commit, this {@link Status} is based on.
......@@ -26,12 +130,12 @@ public class Status {
/**
* A map of files which were changed since the last {@link #commit} and their status codes.
*/
public final Map<Path, String> changed;
public final Map<Path, FileStatus> changed;
/**
* A map of files which are in an unmerged state and their status codes.
*/
public final Map<Path, String> unmerged;
public final Map<Path, FileStatus> unmerged;
/**
* Constructs a new {@link Status}.
......@@ -43,7 +147,7 @@ public class Status {
* @param unmerged
* a map of unmerged files an their status code.
*/
private Status(Commit commit, Map<Path, String> changed, Map<Path, String> unmerged) {
private Status(Commit commit, Map<Path, FileStatus> changed, Map<Path, FileStatus> unmerged) {
this.commit = commit;
this.changed = Collections.unmodifiableMap(changed);
this.unmerged = Collections.unmodifiableMap(unmerged);
......@@ -98,17 +202,25 @@ public class Status {
* @return optionally a {@link Status} object, representing the status read from the git output
*/
static Optional<Status> parseStatus(Repository repo, String gitOutput) {
Map<Path, String> changed = new HashMap<>();
Map<Path, String> unmerged = new HashMap<>();
Map<Path, FileStatus> changed = new HashMap<>();
Map<Path, FileStatus> unmerged = new HashMap<>();
Matcher matcher = STATUS_ENTRY.matcher(gitOutput);
while (matcher.find()) {
// used new path, if file was moved
Path file = Paths.get(matcher.group(2));
String code = matcher.group(1).toUpperCase();
if (code.contains("U")) {
unmerged.put(file, code);
StatusCode x = StatusCode.forChar(code.charAt(0));
StatusCode y = StatusCode.forChar(code.charAt(1));
Path file = Paths.get(matcher.group(2));
Optional<Path> oldFile = Optional.ofNullable(matcher.group(3)).map(Paths::get);
FileStatus status = new FileStatus(x, y, oldFile, file);
if (x == UNMERGED || y == UNMERGED || (x == ADDED && y == ADDED) || (x == DELETED && y == DELETED)) {
unmerged.put(file, status);
} else {
changed.put(file, code);
changed.put(file, status);
}
}
......
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