Index: G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/SVNProviderPlugin.java =================================================================== --- G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/SVNProviderPlugin.java (revision 2694) +++ G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/SVNProviderPlugin.java (working copy) @@ -39,12 +39,12 @@ import org.tigris.subversion.subclipse.core.resources.RepositoryResourcesManager; import org.tigris.subversion.subclipse.core.resourcesListeners.FileModificationManager; import org.tigris.subversion.subclipse.core.resourcesListeners.SyncFileChangeListener; +import org.tigris.subversion.subclipse.core.resourcesListeners.TeamPrivateListener; import org.tigris.subversion.subclipse.core.status.StatusCacheManager; import org.tigris.subversion.subclipse.core.sync.SVNWorkspaceSubscriber; import org.tigris.subversion.subclipse.core.util.ISimpleDialogsHelper; import org.tigris.subversion.svnclientadapter.ISVNClientAdapter; import org.tigris.subversion.svnclientadapter.ISVNPromptUserPassword; -import org.tigris.subversion.subclipse.core.SVNProviderPlugin; /** * The plugin itself @@ -71,6 +71,7 @@ // SVN specific resource delta listeners private FileModificationManager fileModificationManager; private SyncFileChangeListener metaFileSyncListener; + private TeamPrivateListener teamPrivateListener; // the list of all repositories currently handled by this provider private SVNRepositories repositories; @@ -144,6 +145,9 @@ // Initialize SVN change listeners. Note tha the report type is important. IWorkspace workspace = ResourcesPlugin.getWorkspace(); + // this listener will listen to additions of svn meta directories + teamPrivateListener = new TeamPrivateListener(); + // this listener will listen to modifications to files fileModificationManager = new FileModificationManager(); @@ -151,6 +155,8 @@ // subdir) metaFileSyncListener = new SyncFileChangeListener(); + workspace.addResourceChangeListener(teamPrivateListener, + IResourceChangeEvent.POST_CHANGE); workspace.addResourceChangeListener(statusCacheManager, IResourceChangeEvent.PRE_BUILD); workspace.addResourceChangeListener(metaFileSyncListener, @@ -158,6 +164,7 @@ workspace.addResourceChangeListener(fileModificationManager, IResourceChangeEvent.POST_CHANGE); + teamPrivateListener.registerSaveParticipant(); fileModificationManager.registerSaveParticipant(); // Must load the change set manager on startup since it listens to deltas @@ -175,6 +182,7 @@ workspace.removeResourceChangeListener(statusCacheManager); workspace.removeResourceChangeListener(metaFileSyncListener); workspace.removeResourceChangeListener(fileModificationManager); + workspace.removeResourceChangeListener(teamPrivateListener); // save the state which includes the known repositories if (repositories != null) { Index: G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/commands/ShareProjectCommand.java =================================================================== --- G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/commands/ShareProjectCommand.java (revision 2694) +++ G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/commands/ShareProjectCommand.java (working copy) @@ -20,6 +20,8 @@ import org.tigris.subversion.subclipse.core.Policy; import org.tigris.subversion.subclipse.core.SVNException; import org.tigris.subversion.subclipse.core.SVNProviderPlugin; +import org.tigris.subversion.subclipse.core.client.OperationManager; +import org.tigris.subversion.subclipse.core.client.OperationProgressNotifyListener; import org.tigris.subversion.svnclientadapter.ISVNClientAdapter; import org.tigris.subversion.svnclientadapter.SVNClientException; import org.tigris.subversion.svnclientadapter.SVNRevision; @@ -92,9 +94,14 @@ SVNUrl url = location.getUrl().appendPath(remoteDirName); svnClient.mkdir(url, true, message); - // checkout it so that we have .svn - svnClient.checkout(url, project.getLocation() - .toFile(), SVNRevision.HEAD, false); + try { + OperationManager.getInstance().beginOperation(svnClient, new OperationProgressNotifyListener(pm)); + // checkout it so that we have .svn + svnClient.checkout(url, project.getLocation() + .toFile(), SVNRevision.HEAD, false); + } finally { + OperationManager.getInstance().endOperation(); + } } catch (SVNClientException e) { throw new SVNException( "Error while creating module: " Index: G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/resourcesListeners/FileModificationManager.java =================================================================== --- G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/resourcesListeners/FileModificationManager.java (revision 2694) +++ G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/resourcesListeners/FileModificationManager.java (working copy) @@ -16,8 +16,6 @@ import java.util.List; import java.util.Set; -import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; @@ -30,12 +28,9 @@ import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.Path; import org.eclipse.team.core.RepositoryProvider; -import org.tigris.subversion.subclipse.core.Policy; import org.tigris.subversion.subclipse.core.SVNException; import org.tigris.subversion.subclipse.core.SVNProviderPlugin; -import org.tigris.subversion.svnclientadapter.SVNConstants; /** * This class performs several functions related to determining the modified @@ -87,20 +82,11 @@ else if(resource.getType()==IResource.FOLDER) { if (delta.getKind() == IResourceDelta.ADDED) { modifiedInfiniteDepthResources.add(resource); - if (SVNProviderPlugin.getPlugin().isAdminDirectory(resource.getName())) { - handleSVNDir((IContainer) resource, delta.getKind()); - } else { - handleSVNDir(((IContainer) resource).getFolder(new Path(SVNProviderPlugin.getPlugin().getAdminDirectoryName())), delta.getKind()); - } return false; } else if (delta.getKind() == IResourceDelta.REMOVED) { modifiedInfiniteDepthResources.add(resource); return false; - } else if (SVNProviderPlugin.getPlugin().isAdminDirectory(resource.getName())) { - if (handleSVNDir((IContainer)resource, delta.getKind())) { - return false; - } } return true; } @@ -225,34 +211,5 @@ public void saving(ISaveContext context) { } - /** - * If it's a new SVN directory with the canonical child metafiles then mark it as team-private. - * Makr it is team private even when it is changed but not marked team private yet. - * @param svnDir IContainer which is expected to be svn meta directory - * @param kind resourceDelta kind of change - * @return true when the folder folder really is svn meta directory - */ - protected boolean handleSVNDir(IContainer svnDir, int kind) { - if((kind & IResourceDelta.ALL_WITH_PHANTOMS)!=0) { - if ((kind==IResourceDelta.ADDED) || ((kind==IResourceDelta.CHANGED) && !svnDir.isTeamPrivateMember())) - { - // should this dir be made team-private? If it contains Entries then yes! - IFile entriesFile = svnDir.getFile(new Path(SVNConstants.SVN_ENTRIES)); - - if (entriesFile.exists() && !svnDir.isTeamPrivateMember()) { - try { - svnDir.setTeamPrivateMember(true); - if(Policy.DEBUG_METAFILE_CHANGES) { - System.out.println("[svn] found a new SVN meta folder, marking as team-private: " + svnDir.getFullPath()); //$NON-NLS-1$ - } - } catch(CoreException e) { - SVNProviderPlugin.log(SVNException.wrapException(svnDir, Policy.bind("SyncFileChangeListener.errorSettingTeamPrivateFlag"), e)); //$NON-NLS-1$ - } - } - } - } - return svnDir.isTeamPrivateMember(); - } - } Index: G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/resourcesListeners/TeamPrivateListener.java =================================================================== --- G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/resourcesListeners/TeamPrivateListener.java (revision 0) +++ G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/resourcesListeners/TeamPrivateListener.java (revision 0) @@ -0,0 +1,148 @@ +/******************************************************************************* + * Copyright (c) 2003, 2006 Subclipse project and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Subclipse project committers - initial API and implementation + ******************************************************************************/ +package org.tigris.subversion.subclipse.core.resourcesListeners; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.ISaveContext; +import org.eclipse.core.resources.ISaveParticipant; +import org.eclipse.core.resources.ISavedState; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Path; +import org.eclipse.team.core.RepositoryProvider; +import org.tigris.subversion.subclipse.core.Policy; +import org.tigris.subversion.subclipse.core.SVNException; +import org.tigris.subversion.subclipse.core.SVNProviderPlugin; +import org.tigris.subversion.svnclientadapter.SVNConstants; + +/** + * This class listens for additions of subversion meta directories and mark them as + * team private resources. It also registers as a save participant so that deltas + * generated before the plugin are loaded are not missed. + */ +public class TeamPrivateListener implements IResourceChangeListener, ISaveParticipant { + private SVNProviderPlugin provider; + + public TeamPrivateListener() + { + super(); + provider = SVNProviderPlugin.getPlugin(); + } + + /** + * Listen for file modifications + * + * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent) + */ + public void resourceChanged(IResourceChangeEvent event) { + try { + event.getDelta().accept(new IResourceDeltaVisitor() { + public boolean visit(IResourceDelta delta) throws CoreException { + IResource resource = delta.getResource(); + int type = resource.getType(); + + if(type==IResource.FOLDER) { + if (delta.getKind() != IResourceDelta.ADDED) + return true; + if (provider.isAdminDirectory(resource.getName())) { + if (handleSVNDir((IContainer)resource)) { + return false; + } + } + return true; + } + else if (type==IResource.PROJECT) { + IProject project = (IProject)resource; + if (!project.isAccessible()) { + return false; + } + if (RepositoryProvider.getProvider(project, SVNProviderPlugin.getTypeId()) == null) { + return false; // not a svn handled project + } + } + return true; + } + }); + } catch (CoreException e) { + SVNProviderPlugin.log(e.getStatus()); + } + } + + /** + * We register a save participant so we can get the delta from workbench + * startup to plugin startup. + * @throws CoreException + */ + public void registerSaveParticipant() throws CoreException { + IWorkspace ws = ResourcesPlugin.getWorkspace(); + ISavedState ss = ws.addSaveParticipant(SVNProviderPlugin.getPlugin(), this); + if (ss != null) { + ss.processResourceChangeEvents(this); + } + ws.removeSaveParticipant(SVNProviderPlugin.getPlugin()); + } + + /** + * @see org.eclipse.core.resources.ISaveParticipant#doneSaving(org.eclipse.core.resources.ISaveContext) + */ + public void doneSaving(ISaveContext context) { + } + /** + * @see org.eclipse.core.resources.ISaveParticipant#prepareToSave(org.eclipse.core.resources.ISaveContext) + */ + public void prepareToSave(ISaveContext context) { + } + /** + * @see org.eclipse.core.resources.ISaveParticipant#rollback(org.eclipse.core.resources.ISaveContext) + */ + public void rollback(ISaveContext context) { + } + /** + * @see org.eclipse.core.resources.ISaveParticipant#saving(org.eclipse.core.resources.ISaveContext) + */ + public void saving(ISaveContext context) { + } + + /** + * If it's a new SVN directory with the canonical child metafiles then mark it as team-private. + * Makr it is team private even when it is changed but not marked team private yet. + * @param svnDir IContainer which is expected to be svn meta directory + * @param kind resourceDelta kind of change + * @return true when the folder folder really is svn meta directory + */ + public boolean handleSVNDir(IContainer svnDir) { + if (!svnDir.isTeamPrivateMember()) + { + // should this dir be made team-private? If it contains Entries then yes! + IFile entriesFile = svnDir.getFile(new Path(SVNConstants.SVN_ENTRIES)); + + if (entriesFile.exists() && !svnDir.isTeamPrivateMember()) { + try { + svnDir.setTeamPrivateMember(true); + if(Policy.DEBUG_METAFILE_CHANGES) { + System.out.println("[svn] found a new SVN meta folder, marking as team-private: " + svnDir.getFullPath()); //$NON-NLS-1$ + } + } catch(CoreException e) { + SVNProviderPlugin.log(SVNException.wrapException(svnDir, Policy.bind("SyncFileChangeListener.errorSettingTeamPrivateFlag"), e)); //$NON-NLS-1$ + } + } + } + return svnDir.isTeamPrivateMember(); + } +} Property changes on: G:\Shale\AndroMDA\apps\eclipse\workspaces\cleanSubclipse\core\src\org\tigris\subversion\subclipse\core\resourcesListeners\TeamPrivateListener.java ___________________________________________________________________ Name: svn:eol-style + native Index: G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/client/OperationManager.java =================================================================== --- G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/client/OperationManager.java (revision 2694) +++ G:/Shale/AndroMDA/apps/eclipse/workspaces/cleanSubclipse/core/src/org/tigris/subversion/subclipse/core/client/OperationManager.java (working copy) @@ -11,17 +11,19 @@ package org.tigris.subversion.subclipse.core.client; import java.io.File; +import java.util.Iterator; import java.util.LinkedHashSet; -import java.util.Iterator; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.resources.ResourcesPlugin; 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.core.runtime.Path; import org.tigris.subversion.subclipse.core.Policy; @@ -209,17 +211,25 @@ public void setCommand(int command) { } - protected boolean handleSVNDir(IContainer svnDir) { + protected boolean handleSVNDir(final IContainer svnDir) { if (!svnDir.exists() || !svnDir.isTeamPrivateMember()) { try { - if (!svnDir.exists()) { - svnDir.refreshLocal(IResource.DEPTH_ZERO,new NullProgressMonitor()); - } - svnDir.setTeamPrivateMember(true); - if(Policy.DEBUG_METAFILE_CHANGES) { - System.out.println("[svn] found a new SVN meta folder, marking as team-private: " + svnDir.getFullPath()); //$NON-NLS-1$ - } + // important to have both the refresh and setting of team-private in the + // same runnable so that the team-private flag is set before other delta listeners + // sees the SVN folder creation. + ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + if (!svnDir.exists()) { + svnDir.refreshLocal(IResource.DEPTH_ZERO,new NullProgressMonitor()); + } + if (svnDir.exists()) + svnDir.setTeamPrivateMember(true); + if(Policy.DEBUG_METAFILE_CHANGES) { + System.out.println("[svn] found a new SVN meta folder, marking as team-private: " + svnDir.getFullPath()); //$NON-NLS-1$ + } + } + }, svnDir.getParent(), IWorkspace.AVOID_UPDATE, null); } catch(CoreException e) { SVNProviderPlugin.log(SVNException.wrapException(svnDir, Policy.bind("OperationManager.errorSettingTeamPrivateFlag"), e)); //$NON-NLS-1$ }