<commit_before>package hudson.plugins.analysis.util;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.BlameCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.blame.BlameResult;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.jenkinsci.plugins.gitclient.Git;
import org.jenkinsci.plugins.gitclient.GitClient;
import org.jenkinsci.plugins.gitclient.RepositoryCallback;

import hudson.EnvVars;
import hudson.FilePath;
import hudson.model.TaskListener;
import hudson.remoting.VirtualChannel;

/**
 * Assigns git blames to warnings. Based on the solution by <NAME>, see JENKINS-6748.
 *
 * @author <NAME>
 * @see <a href="http://issues.jenkins-ci.org/browse/JENKINS-6748">Issue 6748</a>
 */
public class GitBlamer extends AbstractBlamer {
    private final String pathToGit;

    /**
     * Creates a new blamer for Git.
     *
     * @param pathToGit   path to git binary
     * @param environment {@link EnvVars environment} of the build
     * @param workspace   workspace of the build
     * @param listener    task listener to print logging statements to
     */
    public GitBlamer(final String pathToGit, final EnvVars environment, FilePath workspace, final TaskListener listener) {
        super(environment, workspace, listener);
        this.pathToGit = pathToGit;

        log("Using GitBlamer to create author and commit information for all warnings.%n");
        log("Getting blame results for all files in %s.%n", workspace);
    }

    @Override
    protected Map<String, BlameRequest> blame(final Map<String, BlameRequest> linesOfConflictingFiles) throws InterruptedException, IOException {
        return fillBlameResults(linesOfConflictingFiles, loadBlameResultsForFiles(linesOfConflictingFiles));
    }

    private Map<String, BlameResult> loadBlameResultsForFiles(final Map<String, BlameRequest> linesOfConflictingFiles)
            throws InterruptedException, IOException {
        GitClient git = Git.with(getListener(), getEnvironment()).in(getWorkspace()).using(pathToGit).getClient();
        return git.withRepository(new BlameCallback(this, getHead(git), linesOfConflictingFiles.values()));
    }

    private ObjectId getHead(final GitClient git) throws InterruptedException {
        String gitCommit = getEnvironment().get("GIT_COMMIT");
        ObjectId headCommit;
        if (StringUtils.isBlank(gitCommit)) {
            log("No GIT_COMMIT environment variable found, using HEAD.%n");

            headCommit = git.revParse("HEAD");
        }
        else {
            headCommit = git.revParse(gitCommit);
        }
        return headCommit;
    }<commit_msg>[JENKINS-45572] Don't fail build if git rev-parse throws exception.<commit_after>package hudson.plugins.analysis.util;

import javax.annotation.CheckForNull;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.BlameCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.blame.BlameResult;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.jenkinsci.plugins.gitclient.Git;
import org.jenkinsci.plugins.gitclient.GitClient;
import org.jenkinsci.plugins.gitclient.RepositoryCallback;

import hudson.EnvVars;
import hudson.FilePath;
import hudson.model.TaskListener;
import hudson.plugins.git.GitException;
import hudson.remoting.VirtualChannel;

/**
 * Assigns git blames to warnings. Based on the solution by <NAME>, see JENKINS-6748.
 *
 * @author <NAME>
 * @see <a href="http://issues.jenkins-ci.org/browse/JENKINS-6748">Issue 6748</a>
 */
public class GitBlamer extends AbstractBlamer {
    private final String pathToGit;

    /**
     * Creates a new blamer for Git.
     *
     * @param pathToGit   path to git binary
     * @param environment {@link EnvVars environment} of the build
     * @param workspace   workspace of the build
     * @param listener    task listener to print logging statements to
     */
    public GitBlamer(final String pathToGit, final EnvVars environment, FilePath workspace, final TaskListener listener) {
        super(environment, workspace, listener);
        this.pathToGit = pathToGit;

        log("Using GitBlamer to create author and commit information for all warnings.%n");
        log("Getting blame results for all files in %s.%n", workspace);
    }

    @Override
    protected Map<String, BlameRequest> blame(final Map<String, BlameRequest> linesOfConflictingFiles) throws InterruptedException, IOException {
        return fillBlameResults(linesOfConflictingFiles, loadBlameResultsForFiles(linesOfConflictingFiles));
    }

    private Map<String, BlameResult> loadBlameResultsForFiles(final Map<String, BlameRequest> linesOfConflictingFiles)
            throws InterruptedException, IOException {
        GitClient git = Git.with(getListener(), getEnvironment()).in(getWorkspace()).using(pathToGit).getClient();
        ObjectId headCommit = getHead(git);
        if (headCommit == null) {
            return Collections.emptyMap();
        }
        return git.withRepository(new BlameCallback(this, headCommit, linesOfConflictingFiles.values()));
    }

    @CheckForNull
    private ObjectId getHead(final GitClient git) throws InterruptedException {
        try {
            String gitCommit = getEnvironment().get("GIT_COMMIT");
            ObjectId headCommit;
            if (StringUtils.isBlank(gitCommit)) {
                log("No GIT_COMMIT environment variable found, using HEAD.%n");

                headCommit = git.revParse("HEAD");
            }
            else {
                headCommit = git.revParse(gitCommit);
            }
            return headCommit;
        }
        catch (GitException exception) {
            log("Can't determine head commit using 'git rev-parse'. Skipping blame. %n%s%n", exception.getMessage());
            return null;
        }
    }
{'fraction_non_alphanumeric': 0.09692186266771902, 'fraction_numerical': 0.00489344909234412, 'mean_word_length': 3.618075801749271, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6717558', 'n_tokens_mistral': 1853, 'n_tokens_neox': 1805, 'n_words': 442}