/*******************************************************************************
* 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 org.eclipse.compare.ITypedElement;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.egit.core.internal.storage.CommitFileRevision;
import org.eclipse.egit.core.internal.storage.GitFileRevision;
import org.eclipse.egit.core.internal.storage.IndexFileRevision;
import org.eclipse.egit.core.internal.storage.WorkspaceFileRevision;
import org.eclipse.egit.core.synchronize.GitRemoteResource;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.diffmerge.connector.core.ext.AbstractRevisionScopeDefinitionFactory;
import org.eclipse.emf.diffmerge.connector.git.EMFDiffMergeGitConnectorPlugin;
import org.eclipse.emf.diffmerge.connector.git.Messages;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.team.core.history.IFileRevision;
import org.eclipse.team.core.variants.IResourceVariant;
/**
* A scope definition factory for file revisions in Git repositories,
* index (staging area) excluded.
*/
@SuppressWarnings("restriction") // Specific EGit types
public class GitRevisionScopeDefinitionFactory extends AbstractRevisionScopeDefinitionFactory {
/** The minimal size of commit labels that requires abbreviation */
protected static final int ABBREVIATE_COMMIT_LABEL_SIZE = 7;
/**
* Return an identifier for the given commit ID
* @param revCommit_p a non-null commit ID
* @return a non-null string
*/
protected String getContentIdentifier(RevCommit revCommit_p) {
StringBuilder s = new StringBuilder();
if (revCommit_p != null) {
s.append(revCommit_p.abbreviate(ABBREVIATE_COMMIT_LABEL_SIZE).name());
s.append("..."); //$NON-NLS-1$
PersonIdent authorIdent = revCommit_p.getAuthorIdent();
if (authorIdent != null) {
s.append(" ("); //$NON-NLS-1$
s.append(authorIdent.getName());
s.append(')');
}
}
return s.toString();
}
/**
* @see org.eclipse.emf.diffmerge.connector.core.ext.AbstractRevisionScopeDefinitionFactory#getURIConverterForRevision(org.eclipse.team.core.history.IFileRevision)
*/
@Override
@SuppressWarnings("resource")
protected URIConverter getURIConverterForRevision(IFileRevision revision) throws CoreException {
URIConverter result = null;
IResourceVariant variant = getVariant(revision);
if (variant instanceof GitRemoteResource) {
// Git remote
IPath path = ((GitRemoteResource)variant).getDisplayPath();
Repository repo = GitHelper.INSTANCE.getRepository(path);
if (repo != null)
result = new GitCommitURIConverter(((GitRemoteResource)variant).getCommitId(), repo);
}
if (result == null) {
Repository repo = GitHelper.INSTANCE.getRepository(revision);
if (repo != null) {
if (revision instanceof IndexFileRevision) {
// Git index
try {
if (GitHelper.INSTANCE.isConflicting(revision))
result = new GitIndexTheirsURIConverter(
GitHelper.INSTANCE.getRepository(revision),
((IndexFileRevision)revision).getGitPath());
else
result = new GitIndexURIConverter(GitHelper.INSTANCE.getRepository(revision));
} catch (IOException e) {
EMFDiffMergeGitConnectorPlugin.getDefault().getLog().log(new Status(
IStatus.ERROR, EMFDiffMergeGitConnectorPlugin.getDefault().getPluginId(), e.getMessage(), e));
} catch (NoWorkTreeException e) {
EMFDiffMergeGitConnectorPlugin.getDefault().getLog().log(new Status(
IStatus.ERROR, EMFDiffMergeGitConnectorPlugin.getDefault().getPluginId(), e.getMessage(), e));
}
} else if (revision instanceof CommitFileRevision) {
// Git commit
result = new GitCommitURIConverter(((CommitFileRevision)revision).getRevCommit(), repo);
}
}
}
if (result == null)
result = super.getURIConverterForRevision(revision);
return result;
}
/**
* @see org.eclipse.emf.diffmerge.connector.core.ext.AbstractRevisionScopeDefinitionFactory#getURIForRevision(org.eclipse.team.core.history.IFileRevision)
*/
@Override
protected URI getURIForRevision(IFileRevision revision) throws CoreException {
IResourceVariant variant = getVariant(revision);
final String SCHEME_SEP = ":/"; //$NON-NLS-1$
URI result;
if (variant instanceof GitRemoteResource) {
result = URI.createURI(
GitHelper.INSTANCE.getSchemeRemote() + SCHEME_SEP + ((GitRemoteResource)variant).getPath());
} else if (revision instanceof IndexFileRevision) {
result = URI.createURI(
GitHelper.INSTANCE.getSchemeIndex() + SCHEME_SEP + revision.getURI().toString());
} else if (revision instanceof CommitFileRevision) {
result = URI.createURI(
GitHelper.INSTANCE.getSchemeCommit() + SCHEME_SEP + revision.getURI().toString());
} else {
result = super.getURIForRevision(revision);
}
return result;
}
/**
* @see org.eclipse.emf.diffmerge.connector.core.ext.AbstractRevisionScopeDefinitionFactory#getLabelForRevision(org.eclipse.team.core.history.IFileRevision, org.eclipse.compare.ITypedElement)
*/
@Override
protected String getLabelForRevision(IFileRevision revision_p, ITypedElement entrypoint_p) {
String result;
IResourceVariant variant = getVariant(revision_p);
if (variant instanceof GitRemoteResource) {
result = String.format(Messages.GitRevisionScopeDefinitionFactory_LabelRemote,
revision_p.getName(), variant.getContentIdentifier());
} else if (revision_p instanceof IndexFileRevision) {
result = String.format(Messages.GitRevisionScopeDefinitionFactory_LabelIndex, revision_p.getName());
} else if (revision_p instanceof CommitFileRevision) {
result = String.format(Messages.GitRevisionScopeDefinitionFactory_LabelCommit, revision_p.getName(),
getContentIdentifier(((CommitFileRevision)revision_p).getRevCommit()));
} else if (revision_p instanceof WorkspaceFileRevision) {
result = String.format(Messages.GitRevisionScopeDefinitionFactory_LabelWorkspace, revision_p.getName());
} else {
result = super.getLabelForRevision(revision_p, entrypoint_p);
}
return result;
}
/**
* @see org.eclipse.emf.diffmerge.connector.core.ext.AbstractRevisionScopeDefinitionFactory#isApplicableToRevision(org.eclipse.team.core.history.IFileRevision, org.eclipse.compare.ITypedElement)
*/
@Override
protected boolean isApplicableToRevision(IFileRevision revision_p, ITypedElement entrypoint_p) {
return revision_p instanceof GitFileRevision ||
getVariant(revision_p) instanceof GitRemoteResource;
}
}