blob: 4ef3e3fceb3865ae4f6c41bc9b26302e3c4d860e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Ericsson AB and others.
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Alvaro Sanchez-Leon (Ericsson AB) - Initial API and Implementation
* Sebastien Dubois (Ericsson AB) - Implemented getContributors method
*******************************************************************************/
package org.eclipse.mylyn.internal.subclipse.core;
import java.net.MalformedURLException;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.mylyn.versions.core.ScmArtifact;
import org.eclipse.team.core.history.IFileRevision;
import org.eclipse.team.core.history.provider.FileRevision;
import org.tigris.subversion.subclipse.core.ISVNRemoteResource;
import org.tigris.subversion.subclipse.core.ISVNRepositoryLocation;
import org.tigris.subversion.subclipse.core.SVNException;
import org.tigris.subversion.subclipse.core.commands.GetLogsCommand;
import org.tigris.subversion.subclipse.core.commands.GetRemoteResourceCommand;
import org.tigris.subversion.subclipse.core.history.ILogEntry;
import org.tigris.subversion.subclipse.core.resources.RemoteFile;
import org.tigris.subversion.svnclientadapter.SVNRevision;
import org.tigris.subversion.svnclientadapter.SVNUrl;
/**
* @author Alvaro Sanchez-Leon
*/
@SuppressWarnings("restriction")
public class SubclipseArtifact extends ScmArtifact {
private final SubclipseRepository repository;
private static final ILog logger = SubclipseCorePlugin.getDefault().getLog();
private ISVNRemoteResource svnRemResource = null;
public SubclipseArtifact(String id, String path, SubclipseRepository repository) {
super(id, path);
this.repository = repository;
}
@Override
public IFileRevision getFileRevision(IProgressMonitor monitor) {
try {
final IPath path = Path.fromPortableString(getPath());
return new FileRevision() {
public IFileRevision withAllProperties(IProgressMonitor monitor) throws CoreException {
return this;
}
public boolean isPropertyMissing() {
return false;
}
public IStorage getStorage(IProgressMonitor monitor) throws CoreException {
//If base revision e.g. remote resource is available
if (svnRemResource != null) {
return svnRemResource.getStorage(monitor);
}
final Long revisionNum = Long.decode(getId());
return resolveStorage(monitor, revisionNum, repository.getLocation(), getPath());
}
@Override
public String getContentIdentifier() {
if (null != svnRemResource) {
return svnRemResource.getLastChangedRevision().toString();
}
return null;
}
public String getName() {
return path.lastSegment();
}
};
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public IFileRevision[] getContributors(IProgressMonitor monitor) {
//NOTE: Here we cannot use the ScmResourceArtifact to retrieve the contributors because Subclipse does not
// implement IFileHistory and IFileRevision interfaces. So we will assume that the only contributor is the
// previous version of the artifact.
if (null == svnRemResource) {
return null;
}
//First we have to get the previous revision using the previous ILogEntry.
SVNRevision firstRevision = new SVNRevision.Number(1L);
SVNRevision.Number previousRevision = new SVNRevision.Number(Long.parseLong(getId()));
GetLogsCommand logCmd = new GetLogsCommand(svnRemResource, null, previousRevision, firstRevision, false, 2L,
null, true);
try {
logCmd.run(monitor);
} catch (SVNException e) {
return null;
}
final ILogEntry[] entries = logCmd.getLogEntries();
if (entries.length < 2) {
//No base version found
return null;
}
//Pick the previous revision of the artifact and return it as an IFileRevision
final ISVNRemoteResource remoteResource = entries[entries.length - 1].getRemoteResource();
final IFileRevision[] contributors = new IFileRevision[1];
contributors[0] = new FileRevision() {
public IFileRevision withAllProperties(IProgressMonitor monitor) throws CoreException {
return this;
}
public boolean isPropertyMissing() {
return false;
}
public IStorage getStorage(IProgressMonitor monitor) throws CoreException {
if (null != remoteResource) {
return remoteResource.getStorage(monitor);
}
return null;
}
@Override
public String getContentIdentifier() {
if (null != remoteResource) {
return remoteResource.getLastChangedRevision().toString();
}
return null;
}
public String getName() {
return remoteResource.getName();
}
};
return contributors;
}
@Override
public IFileRevision[] getTargets(IProgressMonitor monitor) {
throw new UnsupportedOperationException();
}
public SVNUrl getRepositoryURL() throws MalformedURLException {
return new SVNUrl(appendToPath(repository.getLocation().getRepositoryRoot().toString(), getPath()));
}
public void setRemoteResource(ISVNRemoteResource remoteResource) {
svnRemResource = remoteResource;
}
/**
* Specific to svn paths as the separator is assumed to be the same for multiple OS
*
* @param aBase
* @param aTail
* @return
*/
private String appendToPath(String aBase, String aTail) {
//initialise with most likely layout
String dBase = aBase;
String dTail = aTail;
if (!aBase.endsWith("/")) { //$NON-NLS-1$
dBase = aBase + "/"; //$NON-NLS-1$
}
if (aTail.startsWith("/")) { //$NON-NLS-1$
dTail = aTail.substring(1);
}
return dBase + dTail;
}
private ISVNRemoteResource resolveRemoteResource(IProgressMonitor monitor, ISVNRepositoryLocation location,
SVNRevision revision, SVNUrl url) throws CoreException {
final GetRemoteResourceCommand command = new GetRemoteResourceCommand(location, url, revision);
command.run(monitor);
final ISVNRemoteResource resource = command.getRemoteResource();
if (resource == null) {
final String msg = "Unable to resolve remote resource for: " + url.toString(); //$NON-NLS-1$
final Status status = new Status(IStatus.ERROR, SubclipseCorePlugin.PLUGIN_ID, msg);
throw new CoreException(status);
}
return resource;
}
private IStorage resolveStorage(IProgressMonitor monitor, Long revNo, ISVNRepositoryLocation location, String path) {
try {
final SVNRevision revision = new SVNRevision.Number(revNo.longValue());
final SVNUrl url = getRepositoryURL();
final ISVNRemoteResource resource = resolveRemoteResource(monitor, location, revision, url);
// check if the resource is a file
if (resource.isFolder()) {
throw new CoreException(new Status(IStatus.ERROR, SubclipseCorePlugin.PLUGIN_ID,
"The path refers to a folder not to a file: " + path)); //$NON-NLS-1$
}
// create remote file with the correct peg revision
final RemoteFile file = new RemoteFile(null, location, url, revision, (SVNRevision.Number) revision, null,
null);
file.setPegRevision(revision);
file.fetchContents(monitor);
return file.getStorage(monitor);
} catch (Exception e) {
logger.log(new Status(IStatus.WARNING, SubclipseCorePlugin.PLUGIN_ID, "Unable to resolve storage, " + revNo //$NON-NLS-1$
+ ", " + path)); //$NON-NLS-1$
return null;
}
}
}