Skip to content
Snippets Groups Projects
CommitReader.java 6.33 KiB
package git;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import issueData.Comment;
import issueData.Issue;
import issueData.User;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.treewalk.TreeWalk;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

class CommitReader {

    private final Repository repo;
    private final List<Issue> issues;
    private final ObjectMapper mapper;
    private Map<String, String> nicknames;

    CommitReader(Repository repo, RevTree commitTree) {
        this.repo = repo;
        this.issues = new ArrayList<>();
        this.nicknames = new HashMap<>();
        mapper = new ObjectMapper();
        buildIssues(commitTree);
    }

    private void buildIssues(RevTree commitTree) {
        try (TreeWalk treeWalk = new TreeWalk(repo)) {
            treeWalk.addTree(commitTree);
            treeWalk.setRecursive(true);

            while (treeWalk.next()) {

                ObjectId blob = treeWalk.getObjectId(0);
                String content = getContent(blob);

                if (treeWalk.getNameString().equals(".nicknames")) {
                    parseNicknames(content);
                    continue;
                }

                String hash = split(treeWalk.getPathString(), 0);

                if (issues.isEmpty() || getIssue(hash) == null) {
                    Issue issue = new Issue();
                    issue.setHash(hash);
                    issues.add(issue);
                    addFieldData(issue, treeWalk.getPathString(), content);
                } else {
                    addFieldData(getIssue(hash), treeWalk.getPathString(), content);
                }
            }

        } catch (IOException e) {
            System.err.println("Make sure no non-issue files have been created on issue branch");
            e.printStackTrace();
        }

    }

    private void parseNicknames(String content) throws IOException {
        this.nicknames = mapper.readValue(content, new TypeReference<Map<String, String>>() {
        });
    }

    private Issue getIssue(String hash) {
        for (Issue issue : issues) {
            if (issue.getHash().equals((hash))) {
                return issue;
            }
        }
        return null;
    }


    private String getContent(ObjectId blob) throws IOException {
        try (ObjectReader objectReader = repo.newObjectReader()) {
            ObjectLoader objectLoader = objectReader.open(blob);
            byte[] bytes = objectLoader.getBytes();
            return new String(bytes, StandardCharsets.UTF_8);
        }
    }

    private byte[] getByteContent(ObjectId blob) throws IOException {
        try (ObjectReader objectReader = repo.newObjectReader()) {
            ObjectLoader objectLoader = objectReader.open(blob);
            return objectLoader.getBytes();
        }
    }

    private void addFieldData(Issue issue, String path, String data) throws IOException {
        String field = split(path, 1);

        switch (field) {
            case "title":
                issue.setTitle(mapper.readValue(data, String.class));
                break;
            case "description":
                issue.setDescription(mapper.readValue(data, String.class));
                break;
            case "creator":
                issue.setCreator(mapper.readValue(data, User.class));
                break;
            case "status":
                issue.setStatus(mapper.readValue(data, boolean.class));
                break;
            case "creationTime":
                issue.setCreationTime(mapper.readValue(data, long.class));
                break;
            case "editTime":
                issue.setEdited(mapper.readValue(data, long.class));
                break;
            case "comments":
                buildComment(issue, path, data);
                break;
            case "tags":
                issue.setTags(mapper.readValue(data, new TypeReference<Set<String>>() {
                }));
                break;
            case "watchers":
                issue.setWatchers(mapper.readValue(data, new TypeReference<Set<User>>() {
                }));
                break;
            case "assignees":
                issue.setAssignees(mapper.readValue(data, new TypeReference<Set<User>>() {
                }));
                break;
            case "attachments":
                System.out.println(path);
                issue.addAttachment(new File(path));
                break;
            default:
                //ignore
                break;
        }
    }

    private void buildComment(Issue issue, String path, String data) throws IOException {
        String commentHash = split(path, 2);
        String commentField = split(path, 3);

        if (issue.getComments().isEmpty() || getComment(issue, commentHash) == null) {
            Comment comment = new Comment();
            comment.setHash(commentHash);
            issue.addComment(comment);
            addCommentFields(comment, commentField, data);
        } else {
            addCommentFields(getComment(issue, commentHash), commentField, data);
        }
    }

    private void addCommentFields(Comment comment, String field, String data) throws IOException {
        switch (field) {
            case "author":
                comment.setAuthor(mapper.readValue(data, User.class));
                break;
            case "message":
                comment.setMessage(mapper.readValue(data, String.class));
                break;
            case "commentTime":
                comment.setCreationTime(mapper.readValue(data, long.class));
                break;
            default:
                //ignore
                break;
        }

    }

    private Comment getComment(Issue issue, String hash) {
        for (Comment comment : issue.getComments()) {
            if (comment.getHash().equals((hash))) {
                return comment;
            }
        }
        return null;
    }

    List<Issue> getIssues() {
        return issues;
    }

    Map<String, String> getNicknames() {
        return nicknames;
    }

    private String split(String path, int index) {
        return path.split("/")[index];
    }

}