All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bazoud.elasticsearch.river.git.guava.functions.CommitIndexFunction Maven / Gradle / Ivy

package com.bazoud.elasticsearch.river.git.guava.functions;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;

import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;

import com.bazoud.elasticsearch.river.git.beans.Commit;
import com.bazoud.elasticsearch.river.git.beans.Context;
import com.bazoud.elasticsearch.river.git.beans.Identity;
import com.bazoud.elasticsearch.river.git.beans.Parent;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Ordering;

import static org.elasticsearch.client.Requests.indexRequest;

/**
 * @author Olivier Bazoud
 */
public class CommitIndexFunction implements Function {
    private static ESLogger logger = Loggers.getLogger(CommitIndexFunction.class);

    @Override
    public Context apply(final Context context) {
        try {
            final RevWalk walk = new RevWalk(context.getRepository());

            walk.markStart(
                FluentIterable
                    .from(context.getRefs())
                    .transform(new Function() {
                        @Override
                        public RevCommit apply(Ref ref) {
                            try {
                                return walk.parseCommit(ref.getObjectId());
                            } catch (Throwable e) {
                                logger.error(this.getClass().getName(), e);
                                return null;
                            }
                        }
                    })
                    .toList()
            );

            final BulkRequestBuilder bulk = context.getClient().prepareBulk();
            FluentIterable
                .from(walk)
                .transform(new Function() {
                    @Override
                    public RevCommit apply(RevCommit commit) {
                        try {
                            bulk.add(indexRequest(context.getIndexName())
                                .type("commit")
                                .id(commit.getId().name())
                                .source(toJson(toCommit(context, walk, commit))));
                            return commit;
                        } catch (Throwable e) {
                            logger.error(this.getClass().getName(), e);
                            return null;
                        }
                    }
                })
                .toList();

            logger.info("Executing bulk {} actions", bulk.numberOfActions());
            if (bulk.numberOfActions() > 0) {
                BulkResponse response = bulk.execute().actionGet();
                logger.info("Bulk actions tooks {} ms", response.getTookInMillis());
                if (response.hasFailures()) {
                    logger.warn("failed to execute bulk: {}", response.buildFailureMessage());
                }
            } else {
                logger.info("Sorry nothing to do");
            }
        } catch(Throwable e) {
            logger.error(this.getClass().getName(), e);
        }

        return context;
    }

    private static Commit toCommit(Context context, RevWalk walk, RevCommit revCommit) throws Exception {
        return Commit.commit()
            .id(revCommit.getId().name())
            .project(context.getName())
            .author(
                Identity.identity()
                    .name(revCommit.getAuthorIdent().getName())
                    .emailAddress(revCommit.getAuthorIdent().getEmailAddress())
                    .when(revCommit.getAuthorIdent().getWhen())
                    .timeZone(revCommit.getAuthorIdent().getTimeZone())
                    .timeZoneOffset(revCommit.getAuthorIdent().getTimeZoneOffset())
                    .build()
            )
            .committer(
                Identity.identity()
                    .name(revCommit.getCommitterIdent().getName())
                    .emailAddress(revCommit.getCommitterIdent().getEmailAddress())
                    .when(revCommit.getCommitterIdent().getWhen())
                    .timeZone(revCommit.getCommitterIdent().getTimeZone())
                    .timeZoneOffset(revCommit.getCommitterIdent().getTimeZoneOffset())
                    .build()
            )
            .subject(revCommit.getShortMessage())
            .messsage(revCommit.getFullMessage())
            .encoding(revCommit.getEncoding().name())
            .issues(parseMessage(context, revCommit.getFullMessage()))
            .parents(
                FluentIterable
                    .from(Arrays.asList(revCommit.getParents()))
                    .transform(new Function() {
                        @Override
                        public Parent apply(RevCommit commit) {
                            try {
                                return Parent.parent()
                                    .id(commit.getId().getName())
                                    .build();
                            } catch (Throwable e) {
                                logger.error(this.getClass().getName(), e);
                                return null;
                            }
                        }
                    })
                    .toList()
            )
            .diff(parseDiff(context, walk, revCommit))
            .build();
    }

    private static String parseDiff(Context context, RevWalk walk, RevCommit revCommit) throws Exception {
        if (context.isIndexingDiff() && revCommit.getParentCount() > 0) {
            RevCommit parentCommit = walk.parseCommit(revCommit.getParent(0).getId());
            ByteArrayOutputStream diffOutputStream = new ByteArrayOutputStream();
            DiffFormatter diffFormatter = new DiffFormatter(diffOutputStream);
            diffFormatter.setRepository(context.getRepository());
            diffFormatter.setDiffComparator(RawTextComparator.DEFAULT);
            diffFormatter.setDetectRenames(true);
            diffFormatter.format(parentCommit.getTree(),revCommit.getTree());
            return new String(diffOutputStream.toByteArray());
        } else {
            return null;
        }
    }

    private static List parseMessage(Context context, String message) {
        if (!context.getIssuePattern().isPresent()) {
            return Collections.emptyList();
        }

        Matcher matcher = context.getIssuePattern().get().matcher(message);
        List issues = new ArrayList();
        while(matcher.find()) {
            issues.add(matcher.group(1));
        }

        return Ordering.natural().sortedCopy(issues);
    }

    private static String toJson(Commit commit) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(commit);
        return json;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy