How to do “git grep -e <pattern>” with jgit?

╄→尐↘猪︶ㄣ 提交于 2021-02-07 09:30:37

问题


I am using "git grep -e " to find files that matches the pattern in content. I looked in the index of jgit, and can't find "grep", but the closest is PatternMatchRevFilter. Is this similar to what "git grep" is doing?

In the official JGit user guide, it says "TODO talk about filters". :) Does someone have an example of how to use this filter?

Thanks!

Jason

ps. this might be a separate question - how can I specify a branch for the search?


回答1:


First off, PatternMatchRevFilter is not the one you want. A RevFilter is for selecting certain revisions (commits) during walking. So it's the equivalent of git log --grep=pattern.

What you want is to walk a tree of a single revision and read the blob contents.

There is not yet a simple to use API for the equivalent of git grep. You have combine the lower-level APIs:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.jgit.diff.RawText;
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.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.TreeWalk;

public class Grep {

    private final Repository repository;
    private final Pattern pattern;

    private final String revName;

    public Grep(Repository repository, Pattern pattern, String revName) {
        this.repository = repository;
        this.pattern = pattern;
        this.revName = revName;
    }

    public void grepPrintingResults() throws IOException {
        ObjectReader objectReader = repository.newObjectReader();
        try {
            ObjectId commitId = repository.resolve(revName);
            impl(objectReader, commitId);
        } finally {
            objectReader.release();
        }
    }

    private void impl(ObjectReader objectReader, ObjectId commitId)
            throws IOException {

        TreeWalk treeWalk = new TreeWalk(objectReader);
        RevWalk revWalk = new RevWalk(objectReader);
        RevCommit commit = revWalk.parseCommit(commitId);

        CanonicalTreeParser treeParser = new CanonicalTreeParser();
        treeParser.reset(objectReader, commit.getTree());

        int treeIndex = treeWalk.addTree(treeParser);
        treeWalk.setRecursive(true);

        while (treeWalk.next()) {
            AbstractTreeIterator it = treeWalk.getTree(treeIndex,
                    AbstractTreeIterator.class);
            ObjectId objectId = it.getEntryObjectId();
            ObjectLoader objectLoader = objectReader.open(objectId);

            if (!isBinary(objectLoader.openStream())) {
                List<String> matchedLines = getMatchedLines(objectLoader
                        .openStream());
                if (!matchedLines.isEmpty()) {
                    String path = it.getEntryPathString();
                    for (String matchedLine : matchedLines) {
                        System.out.println(path + ":" + matchedLine);
                    }
                }
            }
        }
    }

    private List<String> getMatchedLines(InputStream stream) throws IOException {
        BufferedReader buf = null;
        try {
            List<String> matchedLines = new ArrayList<String>();
            InputStreamReader reader = new InputStreamReader(stream, "UTF-8");
            buf = new BufferedReader(reader);
            String line;
            while ((line = buf.readLine()) != null) {
                Matcher m = pattern.matcher(line);
                if (m.find()) {
                    matchedLines.add(line);
                }
            }
            return matchedLines;
        } finally {
            if (buf != null) {
                buf.close();
            }
        }
    }

    private static boolean isBinary(InputStream stream) throws IOException {
        try {
            return RawText.isBinary(stream);
        } finally {
            try {
                stream.close();
            } catch (IOException e) {
                // Ignore, we were just reading
            }
        }
    }
}

Use it like this:

Grep grep = new Grep(repository, Pattern.compile("test"), "HEAD");
grep.grepPrintingResults();


来源:https://stackoverflow.com/questions/15572483/how-to-do-git-grep-e-pattern-with-jgit

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!