/*******************************************************************************
* Copyright (c) 2015-2016 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Stephane Bouchet (Intel Corporation) - initial API and implementation
* Olivier Constant (Thales Global Services) - tight integration
* Stephane Bouchet (Intel Corporation) - bug #496397
*******************************************************************************/
package org.eclipse.emf.diffmerge.connector.git.ext;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.egit.core.Activator;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.egit.ui.internal.revision.LocalFileRevision;
import org.eclipse.emf.diffmerge.connector.git.EMFDiffMergeGitConnectorPlugin;
import org.eclipse.emf.diffmerge.connector.git.Messages;
import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.team.core.history.IFileRevision;
/**
* A helper for Git behaviors.
*/
@SuppressWarnings("restriction") // Specific EGit behaviors
public final class GitHelper {
/** The singleton instance */
public static final GitHelper INSTANCE = new GitHelper();
/** Scheme for remote resources */
private static final String REMOTE_SCHEME = "remote"; //$NON-NLS-1$
/** Scheme for index revisions */
private static final String INDEX_SCHEME = "index"; //$NON-NLS-1$
/** Scheme for commit revisions */
private static final String COMMIT_SCHEME = "commit"; //$NON-NLS-1$
/** Post-scheme separator */
private static final String SCHEME_SEP = ":/"; //$NON-NLS-1$
/**
* Constructor
*/
protected GitHelper() {
// Nothing needed
}
/**
* Return all supported Git schemes
* @return a non-null set
*/
public Collection<String> getGitSchemes() {
return Arrays.asList(getSchemeCommit(), getSchemeIndex(), getSchemeRemote());
}
/**
* Return the Git repository for the given resource path, if any
* @param path_p a non-null path
* @return a potentially null object
*/
public Repository getRepository(IPath path_p) {
// First look directly for connected projects using the repository mapping
if (RepositoryMapping.getMapping(path_p) != null)
return RepositoryMapping.getMapping(path_p).getRepository();
// Then iterate over known repositories.
for (Repository repo: Activator.getDefault().getRepositoryCache().getAllRepositories()) {
Path fullPath=new Path(repo.getWorkTree().toString().concat(path_p.makeAbsolute().toString()));
if (fullPath.toFile().exists())
return repo;
}
EMFDiffMergeGitConnectorPlugin.getDefault().getLog().log(new Status(IStatus.ERROR,
EMFDiffMergeGitConnectorPlugin.getDefault().getPluginId(),
"Cannot find Git repository for resource at: " + path_p)); //$NON-NLS-1$
return null;
}
/**
* Return the Git repository for the given revision
* @param revision_p a potentially null revision
* @return a potentially null object
*/
public Repository getRepository(IFileRevision revision_p) {
if (revision_p != null) {
IPath revisionPath = new Path(revision_p.getURI().toString());
if (!revisionPath.isAbsolute())
return getRepository(revisionPath);
else if (revision_p instanceof LocalFileRevision) {
IFile file = ((LocalFileRevision)revision_p).getFile();
return getRepository(file.getFullPath());
}
EMFDiffMergeGitConnectorPlugin.getDefault().getLog().log(new Status(IStatus.ERROR,
EMFDiffMergeGitConnectorPlugin.getDefault().getPluginId(),
String.format(Messages.GitHelper_NoRepoFound, revisionPath)));
}
return null;
}
/**
* Return the scheme for commit revisions
* @return a non-null string
*/
public String getSchemeCommit() {
return COMMIT_SCHEME;
}
/**
* Return the scheme for index revisions
* @return a non-null string
*/
public String getSchemeIndex() {
return INDEX_SCHEME;
}
/**
* Return the scheme for remote revisions
* @return a non-null string
*/
public String getSchemeRemote() {
return REMOTE_SCHEME;
}
/**
* Return the separator that follows the scheme
* @return a non-null string
*/
public String getSchemeSeparator() {
return SCHEME_SEP;
}
/**
* Return whether there is a conflict on the given revision
* @param revision_p a non-null revision
*/
@SuppressWarnings("resource")
public boolean isConflicting(IFileRevision revision_p)
throws NoWorkTreeException, IOException {
boolean result = false;
Repository repo = getRepository(revision_p);
if (repo != null)
result = isConflicting(repo, revision_p);
return result;
}
/**
* Return whether there is a conflict on the given revision in the given repository
* @param repository_p a non-null repository
* @param revision_p a non-null file revision
* @throws NoWorkTreeException if repository is bare
* @throws IOException if a low-level reading problem occurred
*/
public boolean isConflicting(Repository repository_p,
IFileRevision revision_p) throws NoWorkTreeException, IOException {
IPath revisionPath = new Path(revision_p.getURI().toString());
if (!revisionPath.isAbsolute())
return isConflicting(repository_p, revisionPath.toString());
else if (revision_p instanceof LocalFileRevision) {
IFile file = ((LocalFileRevision)revision_p).getFile();
return isConflicting(repository_p, file.getFullPath().makeRelative().toString());
}
EMFDiffMergeGitConnectorPlugin.getDefault().getLog().log(new Status(IStatus.ERROR,
EMFDiffMergeGitConnectorPlugin.getDefault().getPluginId(),
String.format(Messages.GitHelper_NoConflictInfoFound, revisionPath)));
return false;
}
/**
* Return whether there is a conflict on the given path in the given repository
* @param repository_p a non-null repository
* @param path_p a non-null string
* @throws NoWorkTreeException if repository is bare
* @throws IOException if a low-level reading problem occurred
*/
public boolean isConflicting(Repository repository_p, String path_p)
throws NoWorkTreeException, IOException {
return repository_p.readDirCache().getEntry(path_p).getStage() > 0;
}
}