package org.eclipse.buckminster.subversion;
import java.net.URI;
import java.util.Date;
import org.eclipse.buckminster.core.RMContext;
import org.eclipse.buckminster.core.helpers.TextUtils;
import org.eclipse.buckminster.core.metadata.model.Resolution;
import org.eclipse.buckminster.core.reader.CatalogReaderType;
import org.eclipse.buckminster.core.reader.ITeamReaderType;
import org.eclipse.buckminster.core.reader.ReferenceInfo;
import org.eclipse.buckminster.core.version.VersionMatch;
import org.eclipse.buckminster.core.version.VersionSelector;
import org.eclipse.buckminster.runtime.BuckminsterException;
import org.eclipse.buckminster.runtime.MonitorUtils;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.RepositoryProvider;
public abstract class GenericReaderType<REPO_LOCATION_TYPE, SVN_ENTRY_TYPE, SVN_REVISION_TYPE> extends CatalogReaderType implements ITeamReaderType {
@Override
public ReferenceInfo extractReferenceInfo(String reference) throws CoreException {
String[] parts = TextUtils.split(reference, ","); //$NON-NLS-1$
if (parts.length < 3)
throw BuckminsterException.fromMessage(NLS.bind("The svn readerType cannot parse PSF project reference {0}", reference)); //$NON-NLS-1$
String repositoryLocation = parts[1];
String module = null;
VersionSelector selector = null;
boolean useScheme = false;
int trunkPos = repositoryLocation.indexOf("/trunk"); //$NON-NLS-1$
if (trunkPos > 0) {
// Do we have something after /trunk ?
//
int trunkEnd = trunkPos + 6;
if (repositoryLocation.length() > trunkEnd) {
// We do, then treat that as the module.
//
module = repositoryLocation.substring(trunkEnd);
repositoryLocation = repositoryLocation.substring(0, trunkPos);
useScheme = true;
}
} else {
int branchPos = repositoryLocation.indexOf("/branches/"); //$NON-NLS-1$
if (branchPos > 0) {
// Treat what ever follows directly after /branches/ as a branch
// name
//
int branchNameStart = branchPos + 10;
int branchNameEnd = repositoryLocation.indexOf('/', branchNameStart);
if (branchNameEnd == -1)
branchNameEnd = repositoryLocation.length();
else
module = repositoryLocation.substring(branchNameEnd);
selector = VersionSelector.branch(repositoryLocation.substring(branchNameStart, branchNameEnd));
repositoryLocation = repositoryLocation.substring(0, branchPos);
useScheme = true;
} else {
int tagPos = repositoryLocation.indexOf("/tags/"); //$NON-NLS-1$
if (tagPos > 0) {
// Treat what ever follows directly after /tags/ as a tag
// name
//
int tagNameStart = tagPos + 6;
int tagNameEnd = repositoryLocation.indexOf('/', tagNameStart);
if (tagNameEnd == -1)
tagNameEnd = repositoryLocation.length();
else
module = repositoryLocation.substring(tagNameEnd);
selector = VersionSelector.tag(repositoryLocation.substring(tagNameStart, tagNameEnd));
repositoryLocation = repositoryLocation.substring(0, tagPos);
useScheme = true;
}
}
}
if (useScheme) {
StringBuilder thaUri = new StringBuilder();
thaUri.append(repositoryLocation);
thaUri.append("/trunk"); //$NON-NLS-1$
if (module != null) {
thaUri.append(module);
thaUri.append("?moduleAfterBranch&moduleAfterTag"); //$NON-NLS-1$
} else
thaUri.append("?moduleBeforeBranch&moduleBeforeTag"); //$NON-NLS-1$
repositoryLocation = thaUri.toString();
}
return new ReferenceInfo(repositoryLocation, selector, parts[2]);
}
@Override
final public URI getArtifactURL(Resolution resolution, RMContext context) throws CoreException {
// Left null intentionally
return null;
}
@Override
final public Date getLastModification(String repositoryLocation, VersionSelector versionSelector, IProgressMonitor monitor) throws CoreException {
monitor.beginTask(null, 1);
final ISubversionSession<SVN_ENTRY_TYPE, SVN_REVISION_TYPE> session = getSession(repositoryLocation, versionSelector);
try {
return session.getLastTimestamp();
} finally {
session.close();
MonitorUtils.worked(monitor, 1);
monitor.done();
}
}
@Override
final public long getLastRevision(String repositoryLocation, VersionSelector versionSelector, IProgressMonitor monitor) throws CoreException {
monitor.beginTask(null, 1);
final ISubversionSession<SVN_ENTRY_TYPE, SVN_REVISION_TYPE> session = getSession(repositoryLocation, versionSelector);
try {
return session.getLastChangeNumber();
} finally {
session.close();
MonitorUtils.worked(monitor, 1);
monitor.done();
}
}
@Override
public String getSourceReference(IResource resource, IProgressMonitor monitor) throws CoreException {
String remoteLocation = getRemoteLocation(resource.getLocation().toFile(), monitor);
if (remoteLocation == null)
return null;
return "scm:svn:" + remoteLocation; //$NON-NLS-1$
}
@Override
final public void shareProject(IProject project, Resolution cr, RMContext context, IProgressMonitor monitor) throws CoreException {
VersionMatch vm = cr.getVersionMatch();
String repositoryURI = getRemoteLocation(project.getLocation().toFile(), monitor);
ISubversionSession<SVN_ENTRY_TYPE, SVN_REVISION_TYPE> session = getSession(repositoryURI, vm.getBranchOrTag(), vm.getNumericRevision(),
vm.getTimestamp(), context);
session.createCommonRoots(context);
session = getSession(repositoryURI, vm.getBranchOrTag(), vm.getNumericRevision(), vm.getTimestamp(), context);
try {
updateRepositoryMap(project, session);
} catch (Exception ex) {
throw BuckminsterException.wrap(ex);
} finally {
session.close();
}
}
@Override
public IStatus tag(RepositoryProvider provider, IResource[] resources, String tag, boolean recurse, IProgressMonitor monitor) {
throw new UnsupportedOperationException();
}
abstract protected REPO_LOCATION_TYPE[] getKnownRepositories(IProgressMonitor monitor) throws CoreException;
abstract protected ISubversionSession<SVN_ENTRY_TYPE, SVN_REVISION_TYPE> getSession(String repositoryURI, VersionSelector branchOrTag,
long revision, Date timestamp, RMContext context) throws CoreException;
abstract protected void updateRepositoryMap(IProject project, ISubversionSession<SVN_ENTRY_TYPE, SVN_REVISION_TYPE> session) throws Exception;
private ISubversionSession<SVN_ENTRY_TYPE, SVN_REVISION_TYPE> getSession(String repositoryURI, VersionSelector branchOrTag) throws CoreException {
return getSession(repositoryURI, branchOrTag, -1, null, new RMContext(null));
}
}