package br.uff.ic.dyevc.tools.vcs.git;
//~--- non-JDK imports --------------------------------------------------------
import br.uff.ic.dyevc.application.IConstants;
import br.uff.ic.dyevc.exception.VCSException;
import br.uff.ic.dyevc.model.BranchStatus;
import br.uff.ic.dyevc.model.git.TrackedBranch;
import org.apache.commons.collections15.CollectionUtils;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.CommitCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ListBranchCommand;
import org.eclipse.jgit.api.LogCommand;
import org.eclipse.jgit.api.MergeCommand;
import org.eclipse.jgit.api.MergeResult;
import org.eclipse.jgit.api.PullCommand;
import org.eclipse.jgit.api.PullResult;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.lib.BranchConfig;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.merge.ResolveMerger.MergeFailureReason;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.storage.file.FileRepository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.TrackingRefUpdate;
import org.eclipse.jgit.transport.URIish;
import org.slf4j.LoggerFactory;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* Connects to a git repository, providing a way to invoke commands upon it
*
* @author cristiano
*/
public class GitConnector {
/** Field description */
public static final String GIT_DIR = ".git";
/** Field description */
public static final String DEFAULT_REMOTE = "remote";
/** Field description */
public static final String REFS_REMOTES = "refs/remotes/";
/** Field description */
public static final String FETCH_REFS_HEADS = "+refs/heads/*";
/** Field description */
public static final String DEFAULT_ORIGIN = "origin";
/** Field description */
public static final String CONFIG_FILE = "config";
/** Field description */
public static final String REFS_DEFAULT_BRANCH = "master";
/** Field description */
public static final String KEY_FETCH = "fetch";
/** Field description */
public static final String KEY_URL = "url";
private Repository repository;
private Git git;
private String id;
/**
* Gets the reference to the repository connected to this connector
*
* @return the repository connected to this connector
*/
public Repository getRepository() {
return repository;
}
public String getId() {
return id;
}
/**
* Constructor that connects this class to a repository located at the
* specified path.
*
* @param path location of the repository to connect with
*/
public GitConnector(String path, String name) throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("GitConnector constructor -> Entry.");
try {
repository =
new FileRepositoryBuilder().setGitDir(new File(checkRepositoryPathName(path))).readEnvironment() // scan environment GIT_* variables
.findGitDir() // scan up the file system tree
.build();
git = new Git(repository);
this.id = name;
} catch (IOException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error initializing a GitConnector", ex);
throw new VCSException("Error initializing a git repository.", ex);
}
LoggerFactory.getLogger(GitConnector.class).trace("GitConnector constructor -> Exit.");
}
/**
* Checks if the specified path is a valid repository.
*
* @param path location to check if it is a valid repository
* @return true if the specified path is a valid repository and false if
* it's not.
*/
public static boolean isValidRepository(String path) {
LoggerFactory.getLogger(GitConnector.class).trace("isValidRepository -> Entry.");
LoggerFactory.getLogger(GitConnector.class).debug("Checking if <{}> is a valid repository path.", path);
boolean result;
File file = new File(path);
if (!file.exists()) {
result = false;
LoggerFactory.getLogger(GitConnector.class).debug("Path <{}> IS NOT a valid repository.", path);
} else {
try {
result = new FileRepository(checkRepositoryPathName(path)).getObjectDatabase().exists();
LoggerFactory.getLogger(GitConnector.class).debug("Path <{}> IS a valid repository.", path);
} catch (Throwable t) {
result = false;
}
}
LoggerFactory.getLogger(GitConnector.class).trace("isValidRepository -> Exit.");
return result;
}
/**
* Constructor that connects this class to the specified repository.
*
* @param rep repository to connect to
*/
public GitConnector(Repository rep, String name) {
LoggerFactory.getLogger(GitConnector.class).trace("GitConnector constructor -> Entry.");
repository = rep;
git = new Git(repository);
this.id = name;
LoggerFactory.getLogger(GitConnector.class).trace("GitConnector constructor -> Exit.");
}
/**
* Returns the names of the configured remote repositories for the connected
* repository.
*
* @return the list of known remotes for the connected repository
*/
public Set<String> getRemoteNames() {
LoggerFactory.getLogger(GitConnector.class).trace("getRemoteNames -> Entry.");
Config storedConfig = repository.getConfig();
Set<String> configs = storedConfig.getSubsections("remote");
LoggerFactory.getLogger(GitConnector.class).trace("getRemoteNames -> Exit.");
return configs;
}
/**
* Returns the remote configurations for the connected repository.
*
* @return the list of remote configurations for the connected repository
* @throws URISyntaxException
*/
public List<RemoteConfig> getRemoteConfigs() throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("getRemoteConfigs -> Entry.");
List<RemoteConfig> remoteConfigs = null;
try {
remoteConfigs = RemoteConfig.getAllRemoteConfigs(repository.getConfig());
} catch (URISyntaxException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error reading remote confis.", ex);
throw new VCSException("Error reading remote configs.", ex);
}
LoggerFactory.getLogger(GitConnector.class).trace("getRemoteConfigs -> Exit.");
return remoteConfigs;
}
/**
* Gets the remote name for the specified branch
*
* @param branchName branch to get the remote name
* @return
*/
public String getRemoteForBranch(String branchName) {
LoggerFactory.getLogger(GitConnector.class).trace("getRemoteForBranch -> Entry.");
String remoteName = repository.getConfig().getString("branch", branchName, "remote");
if (remoteName == null) {
remoteName = "origin";
}
LoggerFactory.getLogger(GitConnector.class).trace("getRemoteForBranch -> Exit.");
return remoteName;
}
/**
* Returns the url of a existing remote repository
*
* @return the url of the repository specified by the giving remoteName
*/
public String getRemoteUrl(String remoteName) {
LoggerFactory.getLogger(GitConnector.class).trace("getRemoteUrl -> Entry.");
Config storedConfig = repository.getConfig();
String remoteUrl = storedConfig.getString("remote", remoteName, "url");
LoggerFactory.getLogger(GitConnector.class).trace("getRemoteUrl -> Exit.");
return remoteUrl;
}
/**
* Returns branches with remote tracking configuration
*
* @return
*/
public List<TrackedBranch> getTrackedBranches() {
LoggerFactory.getLogger(GitConnector.class).trace("getTrackedBranches -> Entry.");
List<TrackedBranch> result = new ArrayList<TrackedBranch>();
Config storedConfig = repository.getConfig();
Set<String> trackedBranches = storedConfig.getSubsections("branch");
for (Iterator<String> it = trackedBranches.iterator(); it.hasNext(); ) {
String branchName = it.next();
BranchConfig branchCfg = new BranchConfig(storedConfig, branchName);
TrackedBranch trackedBranch = new TrackedBranch();
trackedBranch.setName(branchName);
trackedBranch.setRemoteName(getRemoteForBranch(branchName));
trackedBranch.setMergeSpec(branchCfg.getRemoteTrackingBranch());
result.add(trackedBranch);
}
LoggerFactory.getLogger(GitConnector.class).trace("getTrackedBranches -> Exit.");
return result;
}
/**
* Returns list of local branches
*
* @return
*/
public Set<String> getLocalBranches() throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("getLocalBranches -> Entry.");
Set<String> result = new TreeSet<String>();
Set<String> all = getAllBranches();
result = new TreeSet(CollectionUtils.subtract(all, getRemoteBranches()));
LoggerFactory.getLogger(GitConnector.class).trace("getLocalBranches -> Exit.");
return result;
}
/**
* Returns list of all branches (local and remote)
*
* @return
*/
public Set<String> getAllBranches() throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("getAllBranches -> Entry.");
Set<String> result = new TreeSet<String>();
try {
List<Ref> branchList = git.branchList().setListMode(ListBranchCommand.ListMode.ALL).call();
for (Iterator<Ref> it = branchList.iterator(); it.hasNext(); ) {
Ref ref = it.next();
result.add(ref.getName());
}
} catch (GitAPIException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error retrieving all branches.", ex);
throw new VCSException("Error retrieving all branches.", ex);
}
LoggerFactory.getLogger(GitConnector.class).trace("getAllBranches -> Exit.");
return result;
}
/**
* Returns list of remote branches
*
* @return
*/
public Set<String> getRemoteBranches() throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("getRemoteBranches -> Entry.");
Set<String> result = new TreeSet<String>();
try {
List<Ref> branchList = git.branchList().setListMode(ListBranchCommand.ListMode.REMOTE).call();
for (Iterator<Ref> it = branchList.iterator(); it.hasNext(); ) {
Ref ref = it.next();
result.add(ref.getName());
}
} catch (GitAPIException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error retrieving remote branches.", ex);
throw new VCSException("Error retrieving all branches.", ex);
}
LoggerFactory.getLogger(GitConnector.class).trace("getRemoteBranches -> Exit.");
return result;
}
/**
* Pulls modifications from the default origin to the repository this
* connector is connected with.
*
* @return whether the pull was successful or not.
* @throws GitAPIException
*/
public PullResult pull() throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("pull -> Entry.");
PullResult result = null;
try {
PullCommand pull = git.pull();
result = pull.call();
LoggerFactory.getLogger(GitConnector.class).debug("Pull finished. Result: \n {}", result.isSuccessful());
} catch (GitAPIException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error during fetch.", ex);
throw new VCSException("Error during pull.", ex);
}
LoggerFactory.getLogger(GitConnector.class).trace("pull -> Exit.");
return result;
}
/**
* Fetches modifications from the default origin to the repository this
* connector is connected with.
*
* @param pruneBranch If true, prune branches that do not exist anymore in
* the source repository which remote name is the same as this repository.
*
* @throws GitAPIException
*/
public FetchResult fetchAllRemotes(boolean pruneBranch) throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("fetchAllRemotes -> Entry. Repository: {}", getId());
FetchResult result = null;
List<RemoteConfig> remotes = getRemoteConfigs();
LoggerFactory.getLogger(GitConnector.class).info("Found {} remotes for repository {}", remotes.size(), getId());
for (Iterator<RemoteConfig> it = remotes.iterator(); it.hasNext(); ) {
RemoteConfig remoteConfig = it.next();
RefSpec refSpec = remoteConfig.getFetchRefSpecs().get(0);
URIish urish = remoteConfig.getURIs().get(0);
boolean prune = pruneBranch && (remoteConfig.getName().equals(getId()));
result = fetch(urish, refSpec, pruneBranch);
}
LoggerFactory.getLogger(GitConnector.class).trace("fetchAllRemotes -> Exit. Repository: {}", getId());
return result;
}
/**
* Fetches modifications from the specified urish to the repository this
* connector is connected with.
*
* @param urish urish representing the remote address
* @param refSpec the ref spec to use in fetch command
* @param pruneBranch If true, prunes branches that does not exist in remote
* repository
*
* @throws GitAPIException
*/
private FetchResult fetch(URIish urish, RefSpec refSpec, boolean pruneBranch) throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("fetch -> Entry. Uri: {}", urish.toString());
FetchResult result = null;
FetchCommand fetch = git.fetch();
fetch.setRemote(checkRepositoryPathName(urish.toString()));
LoggerFactory.getLogger(GitConnector.class).debug("Fetch url: {}", fetch.getRemote());
fetch.setRefSpecs(refSpec);
fetch.setRemoveDeletedRefs(pruneBranch);
try {
result = fetch.call();
StringBuilder msg = new StringBuilder();
for (TrackingRefUpdate update : result.getTrackingRefUpdates()) {
msg.append("\n").append(update.getRemoteName()).append(" : ").append(update.getResult());
}
LoggerFactory.getLogger(GitConnector.class).debug("Fetch from {} finished. Result:{}", urish.toString(),
msg.toString());
} catch (GitAPIException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error during fetch from ." + urish.toString(), ex);
throw new VCSException("Error during fetch from ." + urish.toString(), ex);
}
LoggerFactory.getLogger(GitConnector.class).trace("fetch -> Exit. Uri: {}", urish.toString());
return result;
}
/**
* Pushes modifications from the repository this connector is connected with
* to its default origin
*
* @throws GitAPIException
*/
public void push() throws GitAPIException {
LoggerFactory.getLogger(GitConnector.class).trace("push -> Entry.");
PushCommand push = git.push();
Iterator<PushResult> it = push.call().iterator();
LoggerFactory.getLogger(GitConnector.class).trace("push -> Exit.");
}
/**
* Commits all pending modifications in the repository connected to this
* connector.
*
* @param message commit message
* @throws GitAPIException
*/
public void commit(String message) throws GitAPIException {
LoggerFactory.getLogger(GitConnector.class).trace("commit -> Entry.");
CommitCommand commit = git.commit();
commit.setAll(true);
commit.setMessage(message);
commit.call();
LoggerFactory.getLogger(GitConnector.class).trace("commit -> Exit.");
}
/**
* Gets the reference string for a specified branch in the specified remote
* name.
*
* @param branchName branch to retrieve ref for
* @param remoteName remote name of the repository to look branch ref
* @return the required reference object.
*/
public Ref getBranchRemoteRef(String branchName, String remoteName) throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("getBranchRemoteRef -> Entry.");
Ref ref = null;
try {
String refToFind = REFS_REMOTES + remoteName + "/" + branchName;
ref = repository.getRef(refToFind);
} catch (IOException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error getting remote ref for branch " + branchName
+ " in repository " + remoteName, ex);
throw new VCSException("Error getting remote ref for branch " + branchName + " in repository "
+ remoteName);
}
LoggerFactory.getLogger(GitConnector.class).trace("getOriginRefFromSource -> Exit.");
return ref;
}
public MergeResult merge(Ref anyRef) throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("merge -> Entry.");
MergeResult result = null;
if (anyRef == null) {
LoggerFactory.getLogger(GitConnector.class).debug("Reference is null. Merge will not be executed");
} else {
try {
MergeCommand merge = git.merge();
merge.setStrategy(MergeStrategy.RESOLVE);
merge.include(anyRef);
result = merge.call();
if (!result.getMergeStatus().isSuccessful()) {
StringBuilder msg = new StringBuilder();
msg.append("Error merging repository ").append(getId()).append(". MergeStatus: ").append(
result.getMergeStatus()).append("\nFailing paths:");
Map<String, MergeFailureReason> failingPaths = result.getFailingPaths();
for (Map.Entry<String, MergeFailureReason> entry : failingPaths.entrySet()) {
String path = entry.getKey();
MergeFailureReason mergeFailureReason = entry.getValue();
msg.append("\n\t").append(path).append(". Reason: ").append(mergeFailureReason);
}
LoggerFactory.getLogger(GitConnector.class).warn(msg.toString());
}
} catch (GitAPIException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error during merge.", ex);
throw new VCSException("Error during merge.", ex);
}
}
LoggerFactory.getLogger(GitConnector.class).trace("merge -> Exit.");
return result;
}
/**
* Creates a new repository at the specified path
*
* @param path where the new repository will be created
* @throws IOException
*/
public Repository createRepository(String path) throws IOException {
LoggerFactory.getLogger(GitConnector.class).trace("createRepository -> Entry.");
Repository fileRepo = new FileRepository(checkRepositoryPathName(path));
fileRepo.create();
LoggerFactory.getLogger(GitConnector.class).trace("createRepository -> Exit.");
return fileRepo;
}
/**
* Clone the source repository to the target path
*
* @param source address of the repository to be cloned
* @param target path to clone the repository to
* @return a connector to the clone of this repository
* @throws GitAPIException
*/
public GitConnector cloneRepository(String source, File target, String id) throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("cloneRepository -> Entry.");
CloneCommand cloneCmd = Git.cloneRepository();
cloneCmd.setURI(source);
cloneCmd.setDirectory(target);
cloneCmd.setCloneAllBranches(true);
cloneCmd.setCloneSubmodules(true);
Git result = null;
try {
result = cloneCmd.call();
} catch (GitAPIException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error cloning {} to {}.", source,
target.getAbsolutePath());
LoggerFactory.getLogger(GitConnector.class).error("", ex);
throw new VCSException("Error cloning repository.", ex);
}
GitConnector cloneConnector = new GitConnector(result.getRepository(), id);
LoggerFactory.getLogger(GitConnector.class).trace("cloneRepository -> Exit.");
return cloneConnector;
}
/**
* Method that allows to clone a repository with target represented by a
* String
*
* @param source address of the repository to be cloned
* @param target path to clone the repository to
* @return a connector to the clone of this repository
* @see #cloneRepository(java.lang.String, java.io.File)
* @throws GitAPIException
*/
public GitConnector cloneRepository(String source, String target, String id) throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("cloneRepository -> Entry.");
GitConnector result = cloneRepository(source, new File(target), id);
LoggerFactory.getLogger(GitConnector.class).trace("cloneRepository -> Exit.");
return result;
}
/**
* Method that allows to clone this repository to target represented by a
* String
*
* @param target path to clone the repository to
* @return a connector to the clone of this repository
* @see #cloneRepository(java.lang.String, java.io.File)
* @throws GitAPIException
*/
public GitConnector cloneThis(String target) throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("cloneThis -> Entry.");
GitConnector result = cloneRepository(getPath(), new File(target), this.getId());
LoggerFactory.getLogger(GitConnector.class).trace("cloneThis -> Exit.");
return result;
}
public void close() {
LoggerFactory.getLogger(GitConnector.class).trace("close -> Entry.");
LoggerFactory.getLogger(GitConnector.class).debug("Closing connection with repository <{}>.", getId());
repository.close();
LoggerFactory.getLogger(GitConnector.class).trace("close -> Exit.");
}
public List<BranchStatus> testAhead() throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("testAhead -> Entry.");
List<BranchStatus> result = new ArrayList<BranchStatus>();
List<TrackedBranch> branches = getTrackedBranches();
if (branches == null) {
LoggerFactory.getLogger(GitConnector.class).error(
"There are no tracked branches for repository <{}>, which is located at <{}>.", getId(), getPath());
throw new VCSException("There are no tracked branches for repository <" + getId()
+ ">, which is located at <" + getPath() + ">.");
}
for (Iterator<TrackedBranch> it = branches.iterator(); it.hasNext(); ) {
TrackedBranch trackedBranch = it.next();
BranchStatus relationship = new BranchStatus();
relationship.setRepositoryBranch(trackedBranch.getName());
relationship.setRepositoryUrl(getPath());
relationship.setReferencedRemote(trackedBranch.getRemoteName());
relationship.setMergeSpec(trackedBranch.getMergeSpec());
relationship.setReferencedRepositoryUrl(getRemoteUrl(trackedBranch.getRemoteName()));
try {
WorkingRepositoryBranchStatus status = WorkingRepositoryBranchStatus.of(this, trackedBranch.getName());
if (status != null) {
relationship.setAhead(status.getAheadCount());
relationship.setBehind(status.getBehindCount());
relationship.setListAheadCommitIds(status.getListAheadCommitIds());
relationship.setListBehindCommitIds(status.getListBehindCommitIds());
relationship.setPushURIs(status.getPushURIs());
relationship.setPullURIs(status.getPullURIs());
} else {
LoggerFactory.getLogger(GitConnector.class).warn(
"cannot testAhead branch <{}> declared in repository <{}>.", trackedBranch.getName(), getId());
}
} catch (IOException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error calculating ahead count.", ex);
throw new VCSException("Error calculating ahead count.", ex);
} catch (URISyntaxException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error calculating ahead count.", ex);
throw new VCSException("Error calculating ahead count.", ex);
}
result.add(relationship);
}
LoggerFactory.getLogger(GitConnector.class).trace("testAhead -> Exit.");
return result;
}
/**
* Gets an iterator with all commits that happened to this repository, in
* all branches, whether they are local or remote.
*
* @return the commit history
*/
public Iterator<RevCommit> getAllCommitsIterator() {
LoggerFactory.getLogger(GitConnector.class).trace("getAllCommitsIterator -> Entry.");
Iterator<RevCommit> result = new TreeSet<RevCommit>().iterator();
try {
LogCommand logcmd = git.log();
Map<String, Ref> mapRefsHeads = repository.getRefDatabase().getRefs(IConstants.REFS_HEADS);
Map<String, Ref> mapRefsRemotes = repository.getRefDatabase().getRefs(IConstants.REFS_REMOTES);
for (Map.Entry<String, Ref> entry : mapRefsHeads.entrySet()) {
Ref ref = entry.getValue();
logcmd.add(ref.getObjectId());
}
for (Map.Entry<String, Ref> entry : mapRefsRemotes.entrySet()) {
Ref ref = entry.getValue();
logcmd.add(ref.getObjectId());
}
result = logcmd.call().iterator();
} catch (IOException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error in getAllCommitsIterator.", ex);
} catch (GitAPIException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error in getAllCommitsIterator.", ex);
}
LoggerFactory.getLogger(GitConnector.class).trace("getAllCommitsIterator -> Exit.");
return result;
}
/**
* Gets an iterator with all commits reachable from the specified set of branchHeads.
*
* @param branchHeads the set of branch heads to begin log. Each one of them must be specified in the form
* <b>/ref/heads/<branch name></b>.
* @return the iterator containing all commits reachable from branchHeads
*/
public Iterator<RevCommit> getLogForHeads(Set<String> branchHeads) {
LoggerFactory.getLogger(GitConnector.class).trace("getLogForHeads -> Entry.");
Iterator<RevCommit> result = new TreeSet<RevCommit>().iterator();
try {
LogCommand logcmd = git.log();
for (String ref : branchHeads) {
logcmd.add(repository.resolve(ref));
}
result = logcmd.call().iterator();
} catch (IOException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error in getLogForHeads.", ex);
} catch (GitAPIException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error in getLogForHeads.", ex);
}
LoggerFactory.getLogger(GitConnector.class).trace("getLogForHeads -> Exit.");
return result;
}
/**
* Returns the path to this repository
*
* @return path to this repository
*/
public String getPath() {
LoggerFactory.getLogger(GitConnector.class).trace("getPath -> Entry.");
String path = repository.getDirectory().getAbsolutePath();
LoggerFactory.getLogger(GitConnector.class).trace("getPath -> Exit.");
return path;
}
/**
* Checks if specified path ends with "/.git" and appends it if it doesn't
*
* @param path the path to be checked
* @return a path to a git repository
*/
public static String checkRepositoryPathName(String path) {
LoggerFactory.getLogger(GitConnector.class).trace("checkRepositoryPathName -> Entry.");
String gitPath = path;
if (!path.endsWith(GIT_DIR)) {
if (path.startsWith("http")) {
gitPath = path + GIT_DIR;
} else if (new File(path + "/" + GIT_DIR).exists()) {
gitPath = path + "/" + GIT_DIR;
}
}
LoggerFactory.getLogger(GitConnector.class).trace("checkRepositoryPathName -> Exit.");
return gitPath;
}
public String getRepositoryPath() {
LoggerFactory.getLogger(GitConnector.class).trace("getRepositoryPath -> Entry.");
String gitPath = checkRepositoryPathName(getPath());
LoggerFactory.getLogger(GitConnector.class).trace("getRepositoryPath -> Exit.");
return gitPath;
}
/**
* Returns an object id for a given revision string.
*
* @param revisionString The revision string to be resolved.
* @return the object id corresponding to the specified revision string.
*/
public ObjectId resolve(String revisionString) {
ObjectId result = null;
try {
result = getRepository().resolve(revisionString);
} catch (Exception ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error resolving a reference to " + revisionString, ex);
}
return result;
}
/**
* Returns a map with all tags. Key is the tag name (e.g.: "refs/tags/v1.0") and value
* is the sha-1 of the referenced commit.
*
* @return
*/
public Map<String, String> getAllTags() throws VCSException {
LoggerFactory.getLogger(GitConnector.class).trace("getAllTags -> Entry.");
Map<String, String> result = new TreeMap<String, String>();
try {
List<Ref> tagList = git.tagList().call();
for (Iterator<Ref> it = tagList.iterator(); it.hasNext(); ) {
Ref ref = it.next();
String tagName = ref.getName();
Ref peeledRef = repository.peel(ref);
String commitHash;
if (peeledRef.getPeeledObjectId() == null) {
// tag is a lightweight tag that points directly to the commit
commitHash = peeledRef.getObjectId().getName();
} else {
// tag is not lightweight, wo we get the commit hash from the peeled object
commitHash = peeledRef.getPeeledObjectId().getName();
}
result.put(tagName, commitHash);
}
} catch (GitAPIException ex) {
LoggerFactory.getLogger(GitConnector.class).error("Error retrieving all tags.", ex);
throw new VCSException("Error retrieving all tags.", ex);
}
LoggerFactory.getLogger(GitConnector.class).trace("getAllTags -> Exit.");
return result;
}
}