
no.skatteetaten.aurora.version.git.GitRepo Maven / Gradle / Ivy
Show all versions of aurora-git-version Show documentation
package no.skatteetaten.aurora.version.git;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
/**
* Wrapper which hides the annoying IOExceptions
*/
public class GitRepo {
private final Repository gitRepo;
public GitRepo(Repository gitRepo) {
this.gitRepo = gitRepo;
}
public static GitRepo fromDir(String gitDir) {
return fromDir(new File(gitDir, "."));
}
public static GitRepo fromDir(File gitDir) {
try {
FileRepositoryBuilder builder = new FileRepositoryBuilder();
Repository repository = builder
.setGitDir(new File(gitDir, ".git"))
.readEnvironment() // scan environment GIT_* variables
.setMustExist(true)
.build();
return new GitRepo(repository);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public List getVersionTagsFromCommit(ObjectId commit, String versionPrefix) {
if (commit == null) {
return Collections.emptyList();
}
return withRepo(repository -> {
List tags = new ArrayList<>();
try (Git git = new Git(repository)) {
List call = git.tagList().call();
for (Ref ref : call) {
ObjectId objectId = ref.getObjectId();
Ref peeledRef = repository.peel(ref);
if (peeledRef.getPeeledObjectId() != null) {
objectId = peeledRef.getPeeledObjectId();
}
if (!objectId.equals(commit)) {
continue;
}
String tagName = tagNameFromRef(ref);
if (tagName.startsWith(versionPrefix)) {
tags.add(tagName);
}
}
}
return tags;
});
}
/**
* Get the first log entry with an id matching the given commit id
*/
public Optional getLogEntryForCommit(ObjectId commit) {
if (commit == null) {
return Optional.empty();
}
return withRepo(repository -> {
try (Git git = new Git(repository)) {
Iterable revCommitIterable = git.log().add(commit).call();
return StreamSupport.stream(revCommitIterable.spliterator(), false).findFirst();
}
});
}
private String tagNameFromRef(Ref ref) {
String tagNamePrefix = "refs/tags/";
return ref.getName().replaceFirst(tagNamePrefix, "");
}
public ObjectId resolve(String head) {
return withRepo(repository -> repository.resolve(head));
}
/**
* Determine the name of the current branch. If we are in detached head state, we will fall back to the value of
* the environment variable fallbackBranchNameEnvName
to use as branch name.
*/
public Optional getBranchName(
boolean fallbackToBranchNameEnv,
String fallbackBranchNameEnvName) {
return withRepo(repository -> {
ObjectId head = repository.resolve("HEAD");
String currentBranchName = repository.getBranch();
boolean isDetachedHead = head.getName().equals(currentBranchName);
if (!isDetachedHead) {
return Optional.of(currentBranchName);
}
return getBranchNameFromDetachedHead(head, fallbackToBranchNameEnv, fallbackBranchNameEnvName);
});
}
/**
* If we are trying to determine the branch name of the current commit when we are in detached head
* state, we need to resort to either hints or heuristics. This method will first check for the presence of
* an environment variable called options.fallbackBranchNameEnvName
(default BRANCH_NAME). If it
* exists, its value will be used as branch name (Jenkins sets this environment variable before performing a
* build).
*
* If the environment variable is not set we have to resort to a broad search for the commit. We pick the first
* branch we find the commit in.
*/
public Optional getBranchNameFromDetachedHead(
ObjectId commitId,
boolean fallbackToBranchNameEnv,
String fallbackBranchNameEnvName) {
return withRepo(repository -> {
if (fallbackToBranchNameEnv) {
String branchNameFromEnv = System.getenv(fallbackBranchNameEnvName);
if (branchNameFromEnv != null) {
return Optional.of(branchNameFromEnv);
}
}
RevWalk walk = new RevWalk(repository);
RevCommit commit = walk.parseCommit(repository.resolve(commitId.getName() + "^0"));
return repository.getAllRefs().entrySet().stream()
.filter(e -> e.getKey().startsWith(Constants.R_HEADS))
.filter(e -> {
try {
return walk.isMergedInto(commit, walk.parseCommit(e.getValue().getObjectId()));
} catch (IOException e1) {
return false;
}
})
.map(e -> e.getValue().getName().replaceFirst("refs/heads/", ""))
.findFirst();
});
}
public List getAllVersionsFromTags(String prefix) {
return withRepo(repository -> repository.getTags().entrySet().stream()
.filter(e -> e.getKey().startsWith(prefix))
.map(e -> e.getKey().replaceFirst(prefix, ""))
.collect(Collectors.toList()));
}
public Optional getLogEntryForCurrentHead() {
return getLogEntryForCommit(resolve("HEAD"));
}
private T withRepo(NoExceptionFunction fn) {
try {
return fn.apply(gitRepo);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@FunctionalInterface
public interface NoExceptionFunction {
O apply(I in) throws Exception;
}
}