
com.undefinedlabs.scope.utils.GitUtils Maven / Gradle / Ivy
package com.undefinedlabs.scope.utils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.Edit;
import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.util.io.DisabledOutputStream;
import com.undefinedlabs.scope.utils.metadata.model.GitDiffData;
import com.undefinedlabs.scope.utils.metadata.model.GitDiffFile;
import com.undefinedlabs.scope.utils.metadata.model.GitDiffStatus;
import com.undefinedlabs.scope.utils.props.SystemProps;
import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public enum GitUtils {
INSTANCE;
protected static final String SOURCE_CODE_PATH = "sourceCodePath";
protected static final String REPOSITORY = "repository";
protected static final String COMMIT = "commit";
protected static final String BRANCH = "branch";
protected static final String DIFF = "diff";
private static final Map GIT_INFO_MAP;
private static final String GIT_FOLDER_NAME = ".git";
static {
GIT_INFO_MAP = populateGitInfoMap(SystemProps.USER_DIR, GIT_FOLDER_NAME);
}
public String getSourceRootPath() {
return (String) GIT_INFO_MAP.get(SOURCE_CODE_PATH);
}
public String getRepository() {
return (String) GIT_INFO_MAP.get(REPOSITORY);
}
public String getCommit() {
return (String) GIT_INFO_MAP.get(COMMIT);
}
public String getBranch() {
return (String) GIT_INFO_MAP.get(BRANCH);
}
public GitDiffData getDiff() {
return (GitDiffData) GIT_INFO_MAP.get(DIFF);
}
protected static Map populateGitInfoMap(
final String userDirPath, final String filenameToSearch) {
final File gitFolder = FileUtils.searchBackwardsByFilename(userDirPath, filenameToSearch);
if (gitFolder == null) {
System.err.println(
"Could not locate " + filenameToSearch + " starting from user.dir: " + userDirPath);
return Collections.unmodifiableMap(new HashMap());
}
final Map gitInfoMap = new HashMap<>();
try {
final Git git = Git.open(gitFolder);
final Repository repository = git.getRepository();
final String sourceRootPath = Paths.get(gitFolder.getParent()).toAbsolutePath().toString();
final String repositoryUrl = repository.getConfig().getString("remote", "origin", "url");
final String branch = repository.getBranch();
final ObjectId head = repository.resolve("HEAD");
final String commit = head != null ? head.name() : null;
final GitDiffData diffData = getGitDiffWorkingDir(repository);
gitInfoMap.put(SOURCE_CODE_PATH, sourceRootPath);
gitInfoMap.put(REPOSITORY, repositoryUrl);
gitInfoMap.put(COMMIT, commit);
gitInfoMap.put(BRANCH, branch);
gitInfoMap.put(DIFF, diffData);
} catch (Exception e) {
throw new RuntimeException(e);
}
return Collections.unmodifiableMap(gitInfoMap);
}
private static GitDiffData getGitDiffWorkingDir(Repository repository) {
try {
final DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE);
df.setRepository(repository);
df.setDiffComparator(RawTextComparator.DEFAULT);
df.setDetectRenames(true);
final AbstractTreeIterator commitTreeIterator = prepareTreeParser(repository, Constants.HEAD);
final FileTreeIterator workTreeIterator = new FileTreeIterator(repository);
final List diffEntries = df.scan(commitTreeIterator, workTreeIterator);
final List gitDiffFiles = new ArrayList<>();
for (DiffEntry diffEntry : diffEntries) {
int linesAdded = 0;
int linesDeleted = 0;
for (final Edit edit : df.toFileHeader(diffEntry).toEditList()) {
linesDeleted += edit.getEndA() - edit.getBeginA();
linesAdded += edit.getEndB() - edit.getBeginB();
}
final GitDiffFile diffFile =
new GitDiffFile(
diffEntry.getNewPath(),
linesAdded,
linesDeleted,
GitDiffStatus.parseFrom(diffEntry.getChangeType()),
diffEntry.getOldPath());
gitDiffFiles.add(diffFile);
}
return new GitDiffData(
GitDiffData.TYPE,
GitDiffData.VERSION,
UUID.randomUUID().toString(),
Collections.unmodifiableList(gitDiffFiles));
} catch (Exception e) {
return GitDiffData.EMPTY;
}
}
private static AbstractTreeIterator prepareTreeParser(
final Repository repository, final String ref) throws Exception {
final Ref head = repository.findRef(ref);
if (head == null || head.getObjectId() == null) {
return new EmptyTreeIterator();
}
final RevWalk walk = new RevWalk(repository);
final RevCommit commit = walk.parseCommit(head.getObjectId());
final RevTree tree = walk.parseTree(commit.getTree().getId());
final CanonicalTreeParser oldTreeParser = new CanonicalTreeParser();
try (ObjectReader oldReader = repository.newObjectReader()) {
oldTreeParser.reset(oldReader, tree.getId());
}
return oldTreeParser;
}
public String removeRefs(String branch) {
if (StringUtils.isEmpty(branch)) {
return branch;
}
return branch.startsWith("/refs/heads/")
? branch.replace("/refs/heads/", "")
: branch.startsWith("/refs/") ? branch.replace("/refs/", "") : branch;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy