/******************************************************************************* * Copyright (c) 2004, 2006 * Thomas Hallgren, Kenneth Olwing, Mitch Sonies * Pontus Rydin, Nils Unden, Peer Torngren * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the individual * copyright holders listed above, as Initial Contributors under such license. * The text of such license is available at www.eclipse.org. *******************************************************************************/ package org.eclipse.buckminster.p4.internal; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import org.eclipse.buckminster.core.helpers.FileHandle; import org.eclipse.buckminster.core.helpers.FileUtils; import org.eclipse.buckminster.core.reader.AbstractRemoteReader; import org.eclipse.buckminster.core.reader.IReaderType; import org.eclipse.buckminster.core.version.ProviderMatch; import org.eclipse.buckminster.core.version.VersionMatch; import org.eclipse.buckminster.core.version.VersionSelector; import org.eclipse.buckminster.p4.Messages; import org.eclipse.buckminster.p4.internal.DepotObject.ViewEntry; import org.eclipse.buckminster.runtime.BuckminsterException; import org.eclipse.buckminster.runtime.MonitorUtils; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; /** * @author Thomas Hallgren */ public class P4RemoteReader extends AbstractRemoteReader { public static FileSpec.Specifier getSpecifier(VersionMatch vm, Connection connection, String[] branchName) throws CoreException { FileSpec.Specifier rev = FileSpec.HEAD; VersionSelector branchOrTag = vm.getBranchOrTag(); if(branchOrTag != null) { if(branchOrTag.getType() == VersionSelector.BRANCH) branchName[0] = branchOrTag.getName(); else rev = new FileSpec.Label(branchOrTag.getName()); } boolean specifierConflict = false; long changeNumber = vm.getRevision(); Date timestamp = vm.getTimestamp(); if(changeNumber != -1) { if(rev == FileSpec.HEAD && timestamp == null) rev = new FileSpec.ChangeNumber((int)changeNumber); else specifierConflict = true; } else if(timestamp != null) { if(rev == FileSpec.HEAD) rev = new FileSpec.Timestamp(timestamp.getTime(), connection.getConnectionInfo().getTimeZone()); else specifierConflict = true; } if(specifierConflict) throw new IllegalArgumentException(Messages.tag_timestamp_and_change_number_are_mutually_exclusive); return rev; } private Connection m_connection; private final DepotURI m_depotURI; private FileSpec.Specifier m_revision; public P4RemoteReader(IReaderType readerType, ProviderMatch providerMatch) throws CoreException { super(readerType, providerMatch); VersionMatch vm = providerMatch.getVersionMatch(); String[] branchNameBin = new String[1]; m_depotURI = new DepotURI(providerMatch.getRepositoryURI(), branchNameBin[0], providerMatch.getNodeQuery() .getProperties()); m_revision = getSpecifier(vm, getConnection(), branchNameBin); } public void dropClientEntry(IProgressMonitor monitor) throws CoreException { // Drop this component from the client spec and flush it. // monitor.beginTask(null, IProgressMonitor.UNKNOWN); try { boolean entryDropped = false; IPath depot = getDepotURI().getDepotPath(); Connection conn = getConnection(); ClientSpec client = conn.getClientSpec(); ArrayList<ViewEntry> newSpec = new ArrayList<ViewEntry>(); for(ViewEntry entry : client.getView()) { if(DepotURI.pathEquals(depot, entry.getDepotPath())) entryDropped = true; else newSpec.add(entry); } if(entryDropped) { client.setView(newSpec.toArray(new ViewEntry[newSpec.size()])); client.commitChanges(); conn.exec("flush", new String[] { "..." }); //$NON-NLS-1$ //$NON-NLS-2$ } } finally { monitor.done(); } } public Connection getConnection() throws BuckminsterException { if(m_connection == null) m_connection = new Connection(m_depotURI); return m_connection; } /** * @return Returns the depot locator. */ public final DepotURI getDepotURI() { return m_depotURI; } public void innerMaterialize(IPath destination, IProgressMonitor monitor) throws CoreException { // A previous call to the P4ReaderType must have been made to ensure that the client // spec is set up correctly. // File destFile = destination.toFile(); monitor.beginTask(null, 100); try { FileSpec fileSpec = new FileSpec(destination.append("..."), m_revision); //$NON-NLS-1$ Connection conn = getConnection(); boolean success = false; try { conn.exec("sync", new String[] { "-f", fileSpec.toString() }); //$NON-NLS-1$ //$NON-NLS-2$ MonitorUtils.worked(monitor, 100); success = true; } finally { if(!success) { IProgressMonitor cleanUp = new NullProgressMonitor(); try { dropClientEntry(cleanUp); } catch(CoreException e) { // Ignore } FileUtils.deleteRecursive(destFile, cleanUp); } } } finally { monitor.done(); } } @Override public String toString() { return m_depotURI.toString(); } @Override protected FileHandle innerGetContents(String fileName, IProgressMonitor monitor) throws CoreException, IOException { // Obtain the client spec before we do anything else. This will ensure that the // spec is in sync with our preferences. The spec is cached in the reader type // and later used in materialization so there shouldn't be too much overhead. // ((P4ReaderType)getReaderType()).getClient(m_depotURI); FileSpec fileSpec = new FileSpec(m_depotURI.getDepotPath().append(fileName), m_revision); DepotFile file = getConnection().getFile(fileSpec); if(file == null) throw new FileNotFoundException(fileName); File destFile = createTempFile(); try { file.copyTo(destFile); FileHandle fh = new FileHandle(fileName, destFile, true); destFile = null; return fh; } finally { if(destFile != null) destFile.delete(); } } }