diff options
Diffstat (limited to 'bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderTreeBuilder.java')
-rw-r--r-- | bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderTreeBuilder.java | 734 |
1 files changed, 0 insertions, 734 deletions
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderTreeBuilder.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderTreeBuilder.java deleted file mode 100644 index 89e8d193f..000000000 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFolderTreeBuilder.java +++ /dev/null @@ -1,734 +0,0 @@ -package org.eclipse.team.internal.ccvs.core.resources; - -/* - * (c) Copyright IBM Corp. 2000, 2002. - * All Rights Reserved. - */ - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.eclipse.core.resources.IContainer; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.MultiStatus; -import org.eclipse.core.runtime.Path; -import org.eclipse.team.internal.ccvs.core.CVSException; -import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin; -import org.eclipse.team.internal.ccvs.core.CVSStatus; -import org.eclipse.team.internal.ccvs.core.CVSTag; -import org.eclipse.team.internal.ccvs.core.ICVSFile; -import org.eclipse.team.internal.ccvs.core.ICVSFolder; -import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource; -import org.eclipse.team.internal.ccvs.core.ICVSResource; -import org.eclipse.team.internal.ccvs.core.Policy; -import org.eclipse.team.internal.ccvs.core.client.Command; -import org.eclipse.team.internal.ccvs.core.client.Session; -import org.eclipse.team.internal.ccvs.core.client.Update; -import org.eclipse.team.internal.ccvs.core.client.Command.GlobalOption; -import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption; -import org.eclipse.team.internal.ccvs.core.client.Command.QuietOption; -import org.eclipse.team.internal.ccvs.core.client.listeners.IStatusListener; -import org.eclipse.team.internal.ccvs.core.client.listeners.IUpdateMessageListener; -import org.eclipse.team.internal.ccvs.core.client.listeners.StatusListener; -import org.eclipse.team.internal.ccvs.core.client.listeners.UpdateListener; -import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; -import org.eclipse.team.internal.ccvs.core.connection.CVSServerException; -import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo; -import org.eclipse.team.internal.ccvs.core.syncinfo.MutableResourceSyncInfo; -import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; - -/* - * This class is responsible for building a remote tree that shows the repository - * state of a locally loaded folder tree. - * - * It is used as follows - * - * RemoteFolderTreeBuilder.buildRemoteTree(CVSRepositoryLocation, IManagedFolder, String, IProgressMonitor); - * - * The provider IManagedFolder can be a local resource or a RemoteFolderTree that - * that was previously built. - */ -public class RemoteFolderTreeBuilder { - - private static final int MAX_REVISION_FETCHES_PER_CONNECTION = 1024; - - private Map fileDeltas; - private List changedFiles; - private Map remoteFolderTable; - - private ICVSFolder root; - private RemoteFolderTree remoteRoot; - private CVSRepositoryLocation repository; - - private CVSTag tag; - - private LocalOption[] updateLocalOptions; - - private boolean projectDoesNotExist = false; - - private static String UNKNOWN = ""; //$NON-NLS-1$ - private static String DELETED = "DELETED"; //$NON-NLS-1$ - private static String ADDED = "ADDED"; //$NON-NLS-1$ - private static String FOLDER = "FOLDER"; //$NON-NLS-1$ - - private static Map EMPTY_MAP = new HashMap(); - - static class DeltaNode { - int syncState = Update.STATE_NONE; - String name; - String revision; - - DeltaNode(String name, String revision, int syncState) { - this.name = name; - this.revision = revision; - this.syncState = syncState; - } - - String getName() { - return name; - } - - String getRevision() { - return revision; - } - - int getSyncState() { - return syncState; - } - } - - - private RemoteFolderTreeBuilder(CVSRepositoryLocation repository, ICVSFolder root, CVSTag tag) { - this.repository = repository; - this.root = root; - this.tag = tag; - this.fileDeltas = new HashMap(); - this.changedFiles = new ArrayList(); - this.remoteFolderTable = new HashMap(); - - // Build the local options - List localOptions = new ArrayList(); - localOptions.add(Update.RETRIEVE_ABSENT_DIRECTORIES); - if (tag != null) { - if (tag.getType() == CVSTag.HEAD) { - localOptions.add(Update.CLEAR_STICKY); - } else { - localOptions.add(Update.makeTagOption(tag)); - } - } - updateLocalOptions = (LocalOption[])localOptions.toArray(new LocalOption[localOptions.size()]); - } - - private LocalOption[] getOptionsWithoutTag() { - // Build the local options - List localOptions = new ArrayList(); - localOptions.add(Update.RETRIEVE_ABSENT_DIRECTORIES); - return (LocalOption[])localOptions.toArray(new LocalOption[localOptions.size()]); - } - - public static RemoteFolderTree buildBaseTree(CVSRepositoryLocation repository, ICVSFolder root, CVSTag tag, IProgressMonitor progress) throws CVSException { - try { - RemoteFolderTreeBuilder builder = new RemoteFolderTreeBuilder(repository, root, tag); - progress.beginTask(null, 100); - IProgressMonitor subProgress = Policy.infiniteSubMonitorFor(progress, 100); - subProgress.beginTask(null, 512); //$NON-NLS-1$ - subProgress.subTask(Policy.bind("RemoteFolderTreeBuilder.buildingBase", root.getName())); //$NON-NLS-1$ - return builder.buildBaseTree(null, root, subProgress); - } finally { - progress.done(); - } - } - - public static RemoteFolderTree buildRemoteTree(CVSRepositoryLocation repository, IContainer root, CVSTag tag, IProgressMonitor monitor) throws CVSException { - return buildRemoteTree(repository, CVSWorkspaceRoot.getCVSFolderFor(root), tag, monitor); - } - - public static RemoteFolderTree buildRemoteTree(CVSRepositoryLocation repository, ICVSFolder root, CVSTag tag, IProgressMonitor monitor) throws CVSException { - RemoteFolderTreeBuilder builder = new RemoteFolderTreeBuilder(repository, root, tag); - return builder.buildTree(new ICVSResource[] { root }, monitor); - } - public static RemoteFile buildRemoteTree(CVSRepositoryLocation repository, ICVSFile file, CVSTag tag, IProgressMonitor monitor) throws CVSException { - RemoteFolderTreeBuilder builder = new RemoteFolderTreeBuilder(repository, file.getParent(), tag); - return builder.buildTree(file, monitor); - } - - /* - * The provided resources must all be children of the same project - */ - public static RemoteFolderTree buildRemoteTree(CVSRepositoryLocation repository, ICVSFolder root, ICVSResource[] resources, CVSTag tag, IProgressMonitor monitor) throws CVSException { - if (resources.length == 0) { - resources = new ICVSResource[] { root }; - } - RemoteFolderTreeBuilder builder = new RemoteFolderTreeBuilder(repository, root, tag); - return builder.buildTree(resources, monitor); - } - - private RemoteFolderTree buildTree(ICVSResource[] resources, IProgressMonitor monitor) throws CVSException { - - // Make sure that the cvs commands are not quiet during this operations - QuietOption quietness = CVSProviderPlugin.getPlugin().getQuietness(); - try { - CVSProviderPlugin.getPlugin().setQuietness(Command.VERBOSE); - - monitor.beginTask(null, 100); - - // Get the arguments from the files - ArrayList arguments = new ArrayList(); - for (int i = 0; i < resources.length; i++) { - ICVSResource resource = resources[i]; - arguments.add(resource.getRelativePath(root)); - } - - Policy.checkCanceled(monitor); - Session session = new Session(repository, root, false); - session.open(Policy.subMonitorFor(monitor, 10)); - try { - Policy.checkCanceled(monitor); - fetchDelta(session, (String[]) arguments.toArray(new String[arguments.size()]), Policy.subMonitorFor(monitor, 50)); - if (projectDoesNotExist) { - // We cannot handle the case where a project (i.e. the top-most CVS folder) - // has been deleted directly on the sever (i.e. deleted using rm -rf) - if (root.isCVSFolder() && ! root.isManaged()) { - throw new CVSException(Policy.bind("RemoteFolderTreeBuild.folderDeletedFromServer", root.getFolderSyncInfo().getRepository())); //$NON-NLS-1$ - } else { - return null; - } - } - } finally { - session.close(); - } - // We need a second session because of the use of a different handle on the same remote resource - // Perhaps we could support the changing of a sessions root as long as - // the folder sync info is the same - remoteRoot = - new RemoteFolderTree(null, root.getName(), repository, - new Path(root.getFolderSyncInfo().getRepository()), - tagForRemoteFolder(root, tag)); - session = new Session(repository, remoteRoot, false); - session.open(Policy.subMonitorFor(monitor, 10)); - try { - // Set up an infinite progress monitor for the recursive build - IProgressMonitor subProgress = Policy.infiniteSubMonitorFor(monitor, 30); - subProgress.beginTask(null, 512); - // Build the remote tree - buildRemoteTree(session, root, remoteRoot, Path.EMPTY, subProgress); - // we can only fecth the status for up to 1024 files in a single connection due to - // the server which has a limit on the number of "open" files. - if (!changedFiles.isEmpty() && changedFiles.size() <= MAX_REVISION_FETCHES_PER_CONNECTION) { - fetchFileRevisions(session, (String[])changedFiles.toArray(new String[changedFiles.size()]), Policy.subMonitorFor(monitor, 20)); - } - } finally { - session.close(); - } - - // If there were more than 1024 changed files, we need a connection per each 1024 - if (!changedFiles.isEmpty() && changedFiles.size() > MAX_REVISION_FETCHES_PER_CONNECTION) { - String[] allChangedFiles = (String[])changedFiles.toArray(new String[changedFiles.size()]); - int iterations = (allChangedFiles.length / MAX_REVISION_FETCHES_PER_CONNECTION) - + (allChangedFiles.length % MAX_REVISION_FETCHES_PER_CONNECTION == 0 ? 0 : 1); - for (int i = 0; i < iterations ; i++) { - int length = Math.min(MAX_REVISION_FETCHES_PER_CONNECTION, - allChangedFiles.length - (MAX_REVISION_FETCHES_PER_CONNECTION * i)); - String buffer[] = new String[length]; - System.arraycopy(allChangedFiles, i * MAX_REVISION_FETCHES_PER_CONNECTION, buffer, 0, length); - session = new Session(repository, remoteRoot, false); - session.open(Policy.subMonitorFor(monitor, 1)); - try { - fetchFileRevisions(session, buffer, Policy.subMonitorFor(monitor, 2)); - } finally { - session.close(); - } - } - } - - return remoteRoot; - - } finally { - CVSProviderPlugin.getPlugin().setQuietness(quietness); - monitor.done(); - } - } - private RemoteFile buildTree(ICVSFile file, IProgressMonitor monitor) throws CVSException { - QuietOption quietness = CVSProviderPlugin.getPlugin().getQuietness(); - try { - CVSProviderPlugin.getPlugin().setQuietness(Command.VERBOSE); - - monitor.beginTask(null, 100); - - // Query the server to see if there is a delta available - Policy.checkCanceled(monitor); - Session session = new Session(repository, root, false); - session.open(Policy.subMonitorFor(monitor, 10)); - try { - Policy.checkCanceled(monitor); - fetchDelta(session, new String[] { file.getName() }, Policy.subMonitorFor(monitor, 50)); - if (projectDoesNotExist) { - return null; - } - } finally { - session.close(); - } - // Create a parent for the remote resource - remoteRoot = - new RemoteFolderTree(null, root.getName(), repository, - new Path(root.getFolderSyncInfo().getRepository()), - tagForRemoteFolder(root, tag)); - // Create the remote resource (using the delta if there is one) - RemoteFile remoteFile; - Map deltas = (Map)fileDeltas.get(Path.EMPTY); - if (deltas == null || deltas.isEmpty()) { - // If the file is an addition, return null as the remote - // Note: If there was a conflicting addition, the delta would not be empty - if ( ! file.isManaged() || file.getSyncInfo().isAdded()) { - return null; - } - remoteFile = new RemoteFile(remoteRoot, file.getSyncInfo()); - } else { - DeltaNode d = (DeltaNode)deltas.get(file.getName()); - if (d.getRevision() == DELETED) { - return null; - } - remoteFile = new RemoteFile(remoteRoot, d.getSyncState(), file.getName(), tagForRemoteFolder(remoteRoot, tag)); - } - // Add the resource to its parent - remoteRoot.setChildren(new ICVSRemoteResource[] {remoteFile}); - // If there was a delta, ftech the new revision - if (!changedFiles.isEmpty()) { - // Add the remote folder to the remote folder lookup table (used to update file revisions) - remoteFolderTable.put(new Path(remoteRoot.getFolderSyncInfo().getRemoteLocation()), remoteRoot); - session = new Session(repository, remoteRoot, false); - session.open(Policy.subMonitorFor(monitor, 10)); - try { - fetchFileRevisions(session, (String[])changedFiles.toArray(new String[changedFiles.size()]), Policy.subMonitorFor(monitor, 20)); - } finally { - session.close(); - } - } - return remoteFile; - - } finally { - CVSProviderPlugin.getPlugin().setQuietness(quietness); - monitor.done(); - } - } - - /* - * Build the base remote tree from the local tree. - * - * The localPath is used to retrieve deltas from the recorded deltas - * - * Does 1 work for each managed file and folder - */ - private RemoteFolderTree buildBaseTree(RemoteFolderTree parent, ICVSFolder local, IProgressMonitor monitor) throws CVSException { - - Policy.checkCanceled(monitor); - - // Create a remote folder tree corresponding to the local resource - RemoteFolderTree remote = new RemoteFolderTree(parent, local.getName(), repository, new Path(local.getFolderSyncInfo().getRepository()), local.getFolderSyncInfo().getTag()); - - // Create a List to contain the created children - List children = new ArrayList(); - - // Build the child folders corresponding to local folders base - ICVSResource[] folders = local.members(ICVSFolder.FOLDER_MEMBERS); - for (int i=0;i<folders.length;i++) { - ICVSFolder folder = (ICVSFolder)folders[i]; - if (folder.isManaged() && folder.isCVSFolder()) { - monitor.worked(1); - children.add(buildBaseTree(remote, folder, monitor)); - } - } - - // Build the child files corresponding to local files base - ICVSResource[] files = local.members(ICVSFolder.FILE_MEMBERS); - for (int i=0;i<files.length;i++) { - ICVSFile file = (ICVSFile)files[i]; - ResourceSyncInfo info = file.getSyncInfo(); - // if there is no sync info then there is no base - if (info==null) - continue; - // There is no remote if the file was added - if (info.isAdded()) - continue; - // If the file was deleted locally, we need to generate a new sync info without the delete flag - if (info.isDeleted()) { - MutableResourceSyncInfo undeletedInfo = info.cloneMutable(); - undeletedInfo.setDeleted(false); - info = undeletedInfo; - } - children.add(new RemoteFile(remote, info)); - monitor.worked(1); - } - - // Add the children to the remote folder tree - remote.setChildren((ICVSRemoteResource[])children.toArray(new ICVSRemoteResource[children.size()])); - - return remote; - } - - /* - * Build the remote tree from the local tree and the recorded deltas. - * - * The localPath is used to retrieve deltas from the recorded deltas - * - * Does 1 work for each file and folder delta processed - */ - private void buildRemoteTree(Session session, ICVSFolder local, RemoteFolderTree remote, IPath localPath, IProgressMonitor monitor) throws CVSException { - - Policy.checkCanceled(monitor); - - // Add the remote folder to the remote folder lookup table (used to update file revisions) - remoteFolderTable.put(new Path(remote.getFolderSyncInfo().getRemoteLocation()), remote); - - // Create a map to contain the created children - Map children = new HashMap(); - - // If there's no corresponding local resource then we need to fetch its contents in order to populate the deltas - if (local == null) { - fetchNewDirectory(session, remote, localPath, monitor); - } - - // Fetch the delta's for the folder - Map deltas = (Map)fileDeltas.get(localPath); - if (deltas == null) - deltas = EMPTY_MAP; - - // If there is a local, use the local children to start buidling the remote children - if (local != null) { - // Build the child folders corresponding to local folders - ICVSResource[] folders = local.members(ICVSFolder.FOLDER_MEMBERS); - for (int i=0;i<folders.length;i++) { - ICVSFolder folder = (ICVSFolder)folders[i]; - DeltaNode d = (DeltaNode)deltas.get(folder.getName()); - if (folder.isCVSFolder() && ! isOrphanedSubtree(session, folder) && (d==null || d.getRevision() != DELETED)) { - children.put(folders[i].getName(), - new RemoteFolderTree(remote, folders[i].getName(), repository, - new Path(folder.getFolderSyncInfo().getRepository()), - tagForRemoteFolder(folder,tag))); - } - } - // Build the child files corresponding to local files - ICVSResource[] files = local.members(ICVSFolder.FILE_MEMBERS); - for (int i=0;i<files.length;i++) { - ICVSFile file = (ICVSFile)files[i]; - - DeltaNode d = (DeltaNode)deltas.get(file.getName()); - ResourceSyncInfo info = file.getSyncInfo(); - // if there is no sync info then there isn't a remote file for this local file on the - // server. - if (info==null) - continue; - // There is no remote if the file was added and we didn't get a conflict (C) indicator from the server - if (info.isAdded() && d==null) - continue; - // There is no remote if the file was deleted and we didn;t get a remove (R) indicator from the server - if (info.isDeleted() && d==null) - continue; - - int type = d==null ? Update.STATE_NONE : d.getSyncState(); - children.put(file.getName(), new RemoteFile(remote, type, info)); - } - } - - // Build the children for new or out-of-date resources from the deltas - Iterator i = deltas.keySet().iterator(); - while (i.hasNext()) { - String name = (String)i.next(); - DeltaNode d = (DeltaNode)deltas.get(name); - String revision = d.getRevision(); - if (revision == FOLDER) { - // XXX should getRemotePath() return an IPath instead of a String? - children.put(name, new RemoteFolderTree(remote, repository, - new Path(remote.getRepositoryRelativePath()).append(name), - tagForRemoteFolder(remote, tag))); - } else if (revision == ADDED) { - children.put(name, new RemoteFile(remote, d.getSyncState(), name, tagForRemoteFolder(remote, tag))); - } else if (revision == UNKNOWN) { - // The local resource is out of sync with the remote. - // Create a RemoteFile associated with the tag so we are assured of getting the proper revision - // (Note: this will replace the RemoteFile added from the local base) - children.put(name, new RemoteFile(remote, d.getSyncState(), name, tagForRemoteFolder(remote, tag))); - } else if (revision == DELETED) { - // This should have been deleted while creating from the local resources. - // If it wasn't, delete it now. - if (children.containsKey(name)) - children.remove(name); - } else { - // We should never get here - } - monitor.worked(1); - } - - // Add the children to the remote folder tree - remote.setChildren((ICVSRemoteResource[])children.values().toArray(new ICVSRemoteResource[children.size()])); - - // We have to delay building the child folders to support the proper fetching of new directories - // due to the fact that the same CVS home directory (i.e. the same root directory) must - // be used for all requests sent over the same connection - Iterator childIterator = children.entrySet().iterator(); - List emptyChildren = new ArrayList(); - while (childIterator.hasNext()) { - Map.Entry entry = (Map.Entry)childIterator.next(); - if (((RemoteResource)entry.getValue()).isFolder()) { - RemoteFolderTree remoteFolder = (RemoteFolderTree)entry.getValue(); - String name = (String)entry.getKey(); - ICVSFolder localFolder; - DeltaNode d = (DeltaNode)deltas.get(name); - // for directories that are new on the server - if (d!=null && d.getRevision() == FOLDER) - localFolder = null; - else - localFolder = local.getFolder(name); - buildRemoteTree(session, localFolder, remoteFolder, localPath.append(name), monitor); - // Record any children that are empty - if (pruneEmptyDirectories() && remoteFolder.getChildren().length == 0) { - // Prune if the local folder is also empty. - if (localFolder == null || (localFolder.members(ICVSFolder.ALL_MEMBERS).length == 0)) - emptyChildren.add(remoteFolder); - else { - // Also prune if the tag we are fetching is not HEAD and differs from the tag of the local folder - FolderSyncInfo info = localFolder.getFolderSyncInfo(); - if (tag != null && info != null && ! tag.equals(CVSTag.DEFAULT) && ! tag.equals(info.getTag())) - emptyChildren.add(remoteFolder); - } - } - } - } - - // Prune any empty child folders - if (pruneEmptyDirectories() && !emptyChildren.isEmpty()) { - List newChildren = new ArrayList(); - newChildren.addAll(Arrays.asList(remote.getChildren())); - newChildren.removeAll(emptyChildren); - remote.setChildren((ICVSRemoteResource[])newChildren.toArray(new ICVSRemoteResource[newChildren.size()])); - - } - } - - /* - * This method fetches the delta between the local state and the remote state of the resource tree - * and records the deltas in the fileDeltas instance variable - * - * Returns the list of changed files - */ - private List fetchDelta(Session session, String[] arguments, final IProgressMonitor monitor) throws CVSException { - - // Create an listener that will accumulate new and removed files and folders - final List newChildDirectories = new ArrayList(); - IUpdateMessageListener listener = new IUpdateMessageListener() { - public void directoryInformation(ICVSFolder root, IPath path, boolean newDirectory) { - if (newDirectory) { - // Record new directory with parent so it can be retrieved when building the parent - recordDelta(path, FOLDER, Update.STATE_NONE); - monitor.subTask(Policy.bind("RemoteFolderTreeBuilder.receivingDelta", path.toString())); //$NON-NLS-1$ - // Record new directory to be used as a parameter to fetch its contents - newChildDirectories.add(path.toString()); - } - } - public void directoryDoesNotExist(ICVSFolder root, IPath path) { - // Record removed directory with parent so it can be removed when building the parent - if (path.isEmpty()) { - projectDoesNotExist = true; - } else { - recordDelta(path, DELETED, Update.STATE_NONE); - monitor.subTask(Policy.bind("RemoteFolderTreeBuilder.receivingDelta", path.toString())); //$NON-NLS-1$ - } - } - public void fileInformation(int type, ICVSFolder root, String filename) { - // Cases that do not require action are: - // case 'A' : = A locally added file that does not exists remotely - // case '?' : = A local file that has not been added and does not exists remotely - // case 'M' : = A locally modified file that has not been modified remotely - switch(type) { - case Update.STATE_MERGEABLE_CONFLICT : - case Update.STATE_CONFLICT : - // We have an remote change to a modified local file - // The change could be a local change conflicting with a remote deletion. - // If so, the deltas may already have a DELETED for the file. - // We shouldn't override this DELETED - IPath filePath = new Path(filename); - Map deltas = deltas = (Map)fileDeltas.get(filePath.removeLastSegments(1)); - DeltaNode d = deltas != null ? (DeltaNode)deltas.get(filePath.lastSegment()) : null; - if ((d!=null) && (d.getRevision() == DELETED)) - break; - case Update.STATE_DELETED : // We have a locally removed file that still exists remotely - case Update.STATE_REMOTE_CHANGES : // We have an remote change to an unmodified local file - changedFiles.add(filename); - recordDelta(new Path(filename), UNKNOWN, type); - monitor.subTask(Policy.bind("RemoteFolderTreeBuilder.receivingDelta", filename)); //$NON-NLS-1$ - break; - } - } - public void fileDoesNotExist(ICVSFolder root, String filename) { - recordDelta(new Path(filename), DELETED, Update.STATE_NONE); - monitor.subTask(Policy.bind("RemoteFolderTreeBuilder.receivingDelta", filename)); //$NON-NLS-1$ - } - }; - - // Perform a "cvs -n update -d [-r tag] ." in order to get the - // messages from the server that will indicate what has changed on the - // server. - IStatus status = Command.UPDATE.execute(session, - new GlobalOption[] { Command.DO_NOT_CHANGE }, - updateLocalOptions, - arguments, - new UpdateListener(listener), - monitor); - return changedFiles; - } - /* - * Fetch the children of a previously unknown directory. - * - * The fetch may do up to 2 units of work in the provided monitor. - */ - private void fetchNewDirectory(Session session, RemoteFolderTree newFolder, IPath localPath, final IProgressMonitor monitor) throws CVSException { - - // Create an listener that will accumulate new files and folders - IUpdateMessageListener listener = new IUpdateMessageListener() { - public void directoryInformation(ICVSFolder root, IPath path, boolean newDirectory) { - if (newDirectory) { - // Record new directory with parent so it can be retrieved when building the parent - // NOTE: Check path prefix - recordDelta(path, FOLDER, Update.STATE_NONE); - monitor.subTask(Policy.bind("RemoteFolderTreeBuilder.receivingDelta", path.toString())); //$NON-NLS-1$ - } - } - public void directoryDoesNotExist(ICVSFolder root, IPath path) { - } - public void fileInformation(int type, ICVSFolder root, String filename) { - // NOTE: Check path prefix - changedFiles.add(filename); - recordDelta(new Path(filename), ADDED, type); - monitor.subTask(Policy.bind("RemoteFolderTreeBuilder.receivingDelta", filename)); //$NON-NLS-1$ - } - public void fileDoesNotExist(ICVSFolder root, String filename) { - } - }; - - // NOTE: Should use the path relative to the remoteRoot - IPath path = new Path(newFolder.getRepositoryRelativePath()); - IStatus status = Command.UPDATE.execute(session, - new GlobalOption[] { Command.DO_NOT_CHANGE }, - updateLocalOptions, - new String[] { localPath.toString() }, - new UpdateListener(listener), - Policy.subMonitorFor(monitor, 1)); - if (status.getCode() == CVSStatus.SERVER_ERROR) { - // FIXME: This should be refactored (maybe static methods on CVSException?) - CVSServerException e = new CVSServerException(status); - if ( ! e.isNoTagException() && e.containsErrors()) - throw e; - // we now know that this is an exception caused by a cvs bug. - // if the folder has no files in it (just subfolders) cvs does not respond with the subfolders... - // workaround: retry the request with no tag to get the directory names (if any) - Policy.checkCanceled(monitor); - status = Command.UPDATE.execute(session, - new GlobalOption[] { Command.DO_NOT_CHANGE }, - getOptionsWithoutTag(), - new String[] { localPath.toString() }, - new UpdateListener(listener), - Policy.subMonitorFor(monitor, 1)); - if (status.getCode() == CVSStatus.SERVER_ERROR) { - throw new CVSServerException(status); - } - } - } - - // Get the file revisions for the given filenames - private void fetchFileRevisions(Session session, String[] fileNames, final IProgressMonitor monitor) throws CVSException { - - // Create a listener for receiving the revision info - final Map revisions = new HashMap(); - final List exceptions = new ArrayList(); - IStatusListener listener = new IStatusListener() { - public void fileStatus(ICVSFolder root, IPath path, String remoteRevision) { - try { - updateRevision(path, remoteRevision); - monitor.subTask(Policy.bind("RemoteFolderTreeBuilder.receivingRevision", path.toString())); //$NON-NLS-1$ - } catch (CVSException e) { - exceptions.add(e); - } - } - }; - - // Perform a "cvs status..." with a custom message handler - IStatus status = Command.STATUS.execute(session, - Command.NO_GLOBAL_OPTIONS, - Command.NO_LOCAL_OPTIONS, - fileNames, - new StatusListener(listener), - monitor); - if (status.getCode() == CVSStatus.SERVER_ERROR) { - throw new CVSServerException(status); - } - - // Report any exceptions that occured fecthing the revisions - if ( ! exceptions.isEmpty()) { - if (exceptions.size() == 1) { - throw (CVSException)exceptions.get(0); - } else { - MultiStatus multi = new MultiStatus(CVSProviderPlugin.ID, 0, Policy.bind("RemoteFolder.errorFetchingRevisions"), null); //$NON-NLS-1$ - for (int i = 0; i < exceptions.size(); i++) { - multi.merge(((CVSException)exceptions.get(i)).getStatus()); - } - throw new CVSException(multi); - } - } - } - - private boolean pruneEmptyDirectories() { - return CVSProviderPlugin.getPlugin().getPruneEmptyDirectories(); - } - /* - * Record the deltas in a double map where the outer key is the parent directory - * and the inner key is the file name. The value is the revision of the file or - * DELETED (file or folder). New folders have a revision of FOLDER. - * - * A revison of UNKNOWN indicates that the revision has not been fetched - * from the repository yet. - */ - private void recordDelta(IPath path, String revision, int syncState) { - IPath parent = path.removeLastSegments(1); - Map deltas = (Map)fileDeltas.get(parent); - if (deltas == null) { - deltas = new HashMap(); - fileDeltas.put(parent, deltas); - } - String name = path.lastSegment(); - deltas.put(name, new DeltaNode(name, revision, syncState)); - } - - private void updateRevision(IPath path, String revision) throws CVSException { - RemoteFolderTree folder = (RemoteFolderTree)remoteFolderTable.get(path.removeLastSegments(1)); - if (folder == null) { - throw new CVSException(Policy.bind("RemoteFolderTreeBuilder.missingParent", path.toString(), revision));//$NON-NLS-1$ - } - ((RemoteFile)folder.getFile(path.lastSegment())).setRevision(revision); - } - - /* - * Return the tag that should be associated with a remote folder. - * - * This method is used to ensure that new directories contain the tag - * derived from the parant local folder when appropriate. For instance, - * - * The tag should be the provided tag. However, if tag is null, the - * tag for the folder should be derived from the provided reference folder - * which could be the local resource corresponding to the remote or the parent - * of the remote. - */ - private CVSTag tagForRemoteFolder(ICVSFolder folder, CVSTag tag) throws CVSException { - return tag == null ? folder.getFolderSyncInfo().getTag() : tag; - } - - private boolean isOrphanedSubtree(Session session, ICVSFolder mFolder) throws CVSException { - return mFolder.isCVSFolder() && ! mFolder.isManaged() && ! mFolder.equals(session.getLocalRoot()) && mFolder.getParent().isCVSFolder(); - } -} - |