/******************************************************************************* * Copyright (c) 2006-2013, Cloudsmith Inc. * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the copyright holder * listed above, as the Initial Contributor under such license. The text of * such license is available at www.eclipse.org. ******************************************************************************/ package org.eclipse.buckminster.subversive.internal; import java.io.File; import java.io.OutputStream; import java.net.URI; import java.util.Date; import org.eclipse.buckminster.core.RMContext; import org.eclipse.buckminster.core.helpers.FileUtils; import org.eclipse.buckminster.core.reader.IReaderType; import org.eclipse.buckminster.core.version.ProviderMatch; import org.eclipse.buckminster.core.version.VersionSelector; import org.eclipse.buckminster.runtime.BuckminsterException; import org.eclipse.buckminster.subversion.GenericCache; import org.eclipse.buckminster.subversion.GenericRemoteReader; import org.eclipse.buckminster.subversion.ISubversionSession; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.team.svn.core.connector.ISVNConnector; import org.eclipse.team.svn.core.connector.ISVNProgressMonitor; import org.eclipse.team.svn.core.connector.SVNConnectorException; import org.eclipse.team.svn.core.connector.SVNDepth; import org.eclipse.team.svn.core.connector.SVNEntry; import org.eclipse.team.svn.core.connector.SVNEntryRevisionReference; import org.eclipse.team.svn.core.connector.SVNRevision; import org.eclipse.team.svn.core.operation.file.GetFileContentOperation; /** * The SVN repository reader assumes that any repository contains the three * recommended directories <code>trunk</code>, <code>tags</code>, and * <code>branches</code>. A missing <code>tags</code> directory is interpreted * as no <code>tags</code>. A missing <code>branches</code> directory is * interpreted as no branches. The URL used as the repository identifier must * contain the path element trunk. Anything that follows the <code>trunk</code> * element in the path will be considered a <code>module</code> path. The * repository URL may also contain a query part that in turn may have four * different flags: * <dl> * <dt>moduleBeforeTag</dt> * <dd>When resolving a tag, put the module name between the <code>tags</code> * directory and the actual tag</dd> * <dt>moduleAfterTag</dt> * <dd>When resolving a tag, append the module name after the actual tag</dd> * <dt>moduleBeforeBranch</dt> * <dd>When resolving a branch, put the module name between the * <code>branches</code> directory and the actual branch</dd> * <dt>moduleAfterBranch</dt> * <dd>When resolving a branch, append the module name after the actual branch</dd> * </dl> * A fragment in the repository URL will be treated as a sub-module. It will be * appended at the end of the resolved URL. * * @author Thomas Hallgren * @author Guillaume Chatelet * @author Lorenzo Bettini - * https://bugs.eclipse.org/bugs/show_bug.cgi?id=428301 */ public class SubversiveRemoteFileReader extends GenericRemoteReader<SVNEntry, SVNRevision> { /** * @param readerType * @param rInfo * @param withResolvedBranch * @throws CoreException */ public SubversiveRemoteFileReader(IReaderType readerType, ProviderMatch rInfo, IProgressMonitor monitor) throws CoreException { super(readerType, rInfo, monitor); } @Override protected void fetchRemoteFile(URI url, SVNRevision revision, OutputStream output, IProgressMonitor subMonitor) throws Exception { final ISVNProgressMonitor svnMon = SimpleMonitorWrapper.beginTask(subMonitor, 100); final ISVNConnector proxy = getSession().getSVNProxy(); final SVNEntryRevisionReference entry = new SVNEntryRevisionReference(url.toString(), revision, revision); proxy.streamFileContent(entry, GetFileContentOperation.DEFAULT_BUFFER_SIZE, output, svnMon); } private SubversiveSession getSession() { return (SubversiveSession) session; } @Override protected ISubversionSession<SVNEntry, SVNRevision> getSession(String repositoryURI, VersionSelector branchOrTag, long revision, Date timestamp, RMContext context) throws CoreException { return new SubversiveSession(repositoryURI, branchOrTag, revision, timestamp, context); } @Override protected SVNEntry[] getTopEntries(IProgressMonitor monitor) throws CoreException { return session.listFolder(session.getSVNUrl(), monitor); } @Override public void innerMaterialize(IPath destination, IProgressMonitor monitor) throws CoreException { boolean success = false; File destDir = destination.toFile(); ISVNProgressMonitor svnMon = SimpleMonitorWrapper.beginTask(monitor, 12); try { getSession().getSVNProxy().checkout( new SVNEntryRevisionReference(session.getSVNUrl().toString(), session.getRevision(), session.getRevision()), destDir.toString(), SVNDepth.INFINITY, ISVNConnector.Options.FORCE, svnMon); success = true; } catch (SVNConnectorException e) { throw BuckminsterException.wrap(e); } finally { if (!success) { try { FileUtils.deleteRecursive(destDir, new NullProgressMonitor()); } catch (Throwable t) { t.printStackTrace(); } } monitor.done(); } } @Override protected boolean remoteFileExists(URI url, SVNRevision revision, IProgressMonitor monitor) throws CoreException { return getSession().getDirEntry(url, revision, monitor) != null; } @Override protected String storeInCache(String fileName) throws CoreException { final URI url = session.getSVNUrl(fileName); final SVNRevision revision = session.getRevision(); return GenericCache.cacheKey(url, revision); } }