1 11 package org.eclipse.team.internal.ccvs.core; 12 13 import java.util.ArrayList ; 14 import java.util.List ; 15 16 import org.eclipse.core.resources.*; 17 import org.eclipse.core.resources.mapping.ResourceMapping; 18 import org.eclipse.core.resources.mapping.ResourceTraversal; 19 import org.eclipse.core.runtime.*; 20 import org.eclipse.osgi.util.NLS; 21 import org.eclipse.team.core.*; 22 import org.eclipse.team.core.diff.IDiff; 23 import org.eclipse.team.core.diff.IThreeWayDiff; 24 import org.eclipse.team.core.subscribers.*; 25 import org.eclipse.team.core.synchronize.SyncInfo; 26 import org.eclipse.team.core.synchronize.SyncInfoSet; 27 import org.eclipse.team.core.variants.*; 28 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; 29 import org.eclipse.team.internal.ccvs.core.resources.EclipseSynchronizer; 30 import org.eclipse.team.internal.ccvs.core.syncinfo.*; 31 import org.eclipse.team.internal.ccvs.core.util.ResourceStateChangeListeners; 32 import org.eclipse.team.internal.core.subscribers.ActiveChangeSetManager; 33 34 37 public class CVSWorkspaceSubscriber extends CVSSyncTreeSubscriber implements IResourceStateChangeListener { 38 39 private CVSResourceVariantTree baseTree, remoteTree; 40 41 private static final String REMOTE_RESOURCE_KEY = "remote-resource-key"; 44 private boolean contentFetch; 45 46 CVSWorkspaceSubscriber(QualifiedName id, String name) { 47 super(id, name); 48 49 ResourceVariantByteStore baseSynchronizer = new CVSBaseResourceVariantTree(); 51 baseTree = new CVSResourceVariantTree(baseSynchronizer, null, getCacheFileContentsHint()) { 52 public IResource[] refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { 53 try { 55 monitor.beginTask(null, 100); 56 return new IResource[0]; 57 } finally { 58 monitor.done(); 59 } 60 } 61 }; 62 CVSDescendantResourceVariantByteStore remoteSynchronizer = new CVSDescendantResourceVariantByteStore( 63 baseSynchronizer, 64 new PersistantResourceVariantByteStore(new QualifiedName(SYNC_KEY_QUALIFIER, REMOTE_RESOURCE_KEY))); 65 remoteTree = new CVSResourceVariantTree(remoteSynchronizer, null, getCacheFileContentsHint()) { 66 public boolean isCacheFileContentsHint() { 67 return getCacheFileContentsHint(); 68 } 69 }; 70 71 ResourceStateChangeListeners.getListener().addResourceStateChangeListener(this); 72 } 73 74 82 public IResource[] roots() { 83 List result = new ArrayList (); 84 IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); 85 for (int i = 0; i < projects.length; i++) { 86 IProject project = projects[i]; 87 if(project.isOpen()) { 88 RepositoryProvider provider = RepositoryProvider.getProvider(project, CVSProviderPlugin.getTypeId()); 89 if(provider != null) { 90 result.add(project); 91 } 92 } 93 } 94 return (IProject[]) result.toArray(new IProject[result.size()]); 95 } 96 97 100 public void resourceSyncInfoChanged(IResource[] changedResources) { 101 internalResourceSyncInfoChanged(changedResources, true); 102 } 103 104 private void internalResourceSyncInfoChanged(IResource[] changedResources, boolean canModifyWorkspace) { 105 getRemoteByteStore().handleResourceChanges(changedResources, canModifyWorkspace); 106 fireTeamResourceChange(SubscriberChangeEvent.asSyncChangedDeltas(this, changedResources)); 107 } 108 109 112 public void externalSyncInfoChange(IResource[] changedResources) { 113 internalResourceSyncInfoChanged(changedResources, false); 114 } 115 116 119 public void resourceModified(IResource[] changedResources) { 120 124 } 127 128 131 public void projectConfigured(IProject project) { 132 SubscriberChangeEvent delta = new SubscriberChangeEvent(this, ISubscriberChangeEvent.ROOT_ADDED, project); 133 fireTeamResourceChange(new SubscriberChangeEvent[] {delta}); 134 } 135 136 139 public void projectDeconfigured(IProject project) { 140 try { 141 getRemoteTree().flushVariants(project, IResource.DEPTH_INFINITE); 142 } catch (TeamException e) { 143 CVSProviderPlugin.log(e); 144 } 145 SubscriberChangeEvent delta = new SubscriberChangeEvent(this, ISubscriberChangeEvent.ROOT_REMOVED, project); 146 fireTeamResourceChange(new SubscriberChangeEvent[] {delta}); 147 } 148 149 public void setRemote(IResource resource, IResourceVariant remote, IProgressMonitor monitor) throws TeamException { 150 IResource[] changedResources = 152 ((CVSResourceVariantTree)getRemoteTree()).collectChanges(resource, remote, IResource.DEPTH_INFINITE, monitor); 153 if (changedResources.length != 0) { 154 fireTeamResourceChange(SubscriberChangeEvent.asSyncChangedDeltas(this, changedResources)); 155 } 156 } 157 158 161 protected IResourceVariantTree getBaseTree() { 162 return baseTree; 163 } 164 165 168 protected IResourceVariantTree getRemoteTree() { 169 return remoteTree; 170 } 171 172 175 public void collectOutOfSync(IResource[] resources, int depth, final SyncInfoSet set, final IProgressMonitor monitor) { 176 monitor.beginTask(null, IProgressMonitor.UNKNOWN); 177 for (int i = 0; i < resources.length; i++) { 178 IResource resource = resources[i]; 179 try { 180 if (!isSupervised(resource)) { 181 return; 182 } 183 } catch (TeamException e) { 184 CVSProviderPlugin.log(e); 186 } 187 try { 188 visit(resource, new IResourceVisitor() { 189 public boolean visit(IResource innerResource) throws CoreException { 190 try { 191 Policy.checkCanceled(monitor); 192 if (innerResource.getType() != IResource.FILE) { 193 monitor.subTask(NLS.bind(CVSMessages.CVSWorkspaceSubscriber_1, new String [] { innerResource.getFullPath().toString() })); 194 } 195 if (isOutOfSync(innerResource, monitor)) { 196 SyncInfo info = getSyncInfo(innerResource); 197 if (info != null && info.getKind() != 0) { 198 set.add(info); 199 } 200 } 201 } catch (TeamException e) { 202 set.addError(new TeamStatus( 203 IStatus.ERROR, CVSProviderPlugin.ID, ITeamStatus.RESOURCE_SYNC_INFO_ERROR, 204 NLS.bind(CVSMessages.CVSWorkspaceSubscriber_2, new String [] { innerResource.getFullPath().toString(), e.getMessage() }), e, innerResource)); 205 } 206 return true; 207 } 208 }, depth); 209 } catch (CoreException e) { 210 set.addError(new TeamStatus( 211 IStatus.ERROR, CVSProviderPlugin.ID, ITeamStatus.SYNC_INFO_SET_ERROR, 212 e.getMessage(), e, ResourcesPlugin.getWorkspace().getRoot())); 213 } 214 } 215 monitor.done(); 216 } 217 218 private void visit(IResource resource, IResourceVisitor visitor, int depth) throws CoreException { 219 boolean keepGoing = visitor.visit(resource); 220 if (keepGoing && depth != IResource.DEPTH_ZERO) { 221 IResource[] members = members(resource); 222 for (int i = 0; i < members.length; i++) { 223 IResource member = members[i]; 224 visit(member, visitor, depth == IResource.DEPTH_ONE ? IResource.DEPTH_ZERO : IResource.DEPTH_INFINITE); 225 } 226 } 227 } 228 229 boolean isOutOfSync(IResource resource, IProgressMonitor monitor) throws TeamException { 230 return (hasIncomingChange(resource) || hasOutgoingChange(resource, monitor)); 231 } 232 233 private boolean hasIncomingChange(IResource resource) throws TeamException { 234 return getRemoteByteStore().isVariantKnown(resource); 235 } 236 237 private boolean hasOutgoingChange(IResource resource, IProgressMonitor monitor) throws CVSException { 238 if (resource.getType() == IResource.PROJECT || resource.getType() == IResource.ROOT) { 239 return false; 241 } 242 int state = EclipseSynchronizer.getInstance().getModificationState(resource.getParent()); 243 if (state == ICVSFile.CLEAN) { 244 return false; 246 } 247 if (resource.getType() == IResource.FILE) { 248 ICVSFile file = CVSWorkspaceRoot.getCVSFileFor((IFile)resource); 250 return file.isModified(monitor); 251 } else { 252 ICVSFolder folder = CVSWorkspaceRoot.getCVSFolderFor((IContainer)resource); 254 return !folder.isCVSFolder() && !folder.isIgnored(); 255 } 256 } 257 258 261 private CVSDescendantResourceVariantByteStore getRemoteByteStore() { 262 return (CVSDescendantResourceVariantByteStore)((CVSResourceVariantTree)getRemoteTree()).getByteStore(); 263 } 264 265 270 public void updateRemote(CVSTeamProvider provider, ICVSFolder folder, boolean recurse, IProgressMonitor monitor) throws TeamException { 271 try { 272 monitor.beginTask(null, IProgressMonitor.UNKNOWN); 273 IResource resource = folder.getIResource(); 274 if (resource != null) { 275 ICVSResource tree = buildBaseTree( 276 resource, 277 false, 278 Policy.subMonitorFor(monitor, 50)); 279 setRemote(resource, (IResourceVariant)tree, Policy.subMonitorFor(monitor, 50)); 280 } 281 } finally { 282 monitor.done(); 283 } 284 } 285 286 public ICVSRemoteResource buildBaseTree(IResource resource, boolean immutable, IProgressMonitor monitor) throws TeamException { 287 try { 288 monitor.beginTask(null, IProgressMonitor.UNKNOWN); 289 return ((CVSResourceVariantTree)getBaseTree()).buildTree(null, resource, immutable, monitor); 290 } finally { 291 monitor.done(); 292 } 293 } 294 295 public ICVSRemoteResource buildRemoteTree(IResource resource, boolean immutable, IProgressMonitor monitor) throws TeamException { 296 try { 297 monitor.beginTask(null, IProgressMonitor.UNKNOWN); 298 return ((CVSResourceVariantTree)getRemoteTree()).buildTree(null, resource, immutable, monitor); 299 } finally { 300 monitor.done(); 301 } 302 } 303 304 307 public int getState(ResourceMapping mapping, int stateMask, IProgressMonitor monitor) throws CoreException { 308 if ((stateMask & IThreeWayDiff.INCOMING) == 0) { 309 ResourceTraversal[] traversals = mapping.getTraversals(new SubscriberResourceMappingContext(this, false), monitor); 311 if (hasLocalChanges(traversals, monitor)) { 312 int state = IThreeWayDiff.OUTGOING; 313 state |= getOutgoingKind(traversals, monitor); 314 return state; 315 } else { 316 return 0; 317 } 318 } 319 return super.getState(mapping, stateMask, monitor); 320 } 321 322 private int getOutgoingKind(ResourceTraversal[] traversals, IProgressMonitor monitor) throws CoreException { 323 int kind = 0; 324 for (int i = 0; i < traversals.length; i++) { 325 ResourceTraversal traversal = traversals[i]; 326 IResource[] resources = traversal.getResources(); 327 for (int j = 0; j < resources.length; j++) { 328 IResource resource = resources[j]; 329 IDiff node = getDiff(resource); 330 if (node == null) 331 return IDiff.CHANGE; 332 int nextKind = node.getKind(); 333 if (kind == 0) 334 kind = nextKind; 335 if (nextKind != kind || nextKind == IDiff.CHANGE) 336 return IDiff.CHANGE; 337 } 338 } 339 return kind; 340 } 341 342 345 public boolean hasLocalChanges(ResourceTraversal[] traversals, IProgressMonitor monitor) throws CoreException { 346 monitor = Policy.monitorFor(monitor); 347 for (int i = 0; i < traversals.length; i++) { 348 ResourceTraversal traversal = traversals[i]; 349 IResource[] resources = traversal.getResources(); 350 switch (traversal.getDepth()) { 351 case IResource.DEPTH_ZERO: 352 for (int j = 0; j < resources.length; j++) { 353 IResource resource = resources[j]; 354 if (isDirectlyDirty(resource, monitor)) { 355 return true; 356 } 357 } 358 break; 359 case IResource.DEPTH_INFINITE: 360 for (int j = 0; j < resources.length; j++) { 361 IResource resource = resources[j]; 362 if (isDirty(resource, monitor)) { 363 return true; 364 } 365 } 366 break; 367 case IResource.DEPTH_ONE: 368 for (int j = 0; j < resources.length; j++) { 369 IResource resource = resources[j]; 370 if (isDirectlyDirty(resource, monitor)) { 371 return true; 372 } 373 IResource[] children = members(resource); 374 for (int k = 0; k < children.length; k++) { 375 IResource child = children[k]; 376 if (isDirectlyDirty(child, monitor)) { 377 return true; 378 } 379 } 380 } 381 break; 382 } 383 } 384 return false; 385 } 386 387 private boolean isDirectlyDirty(IResource resource, IProgressMonitor monitor) throws CoreException { 388 if (resource.getType() == IResource.FILE) { 389 if (isDirty(resource, monitor)) 390 return true; 391 } else { 392 IDiff node = getDiff(resource); 393 if (node != null 394 && node instanceof IThreeWayDiff 395 && ((IThreeWayDiff)node).getLocalChange() != null 396 && ((IThreeWayDiff)node).getLocalChange().getKind() != IDiff.NO_CHANGE) 397 return true; 398 } 399 return false; 400 } 401 402 public boolean isDirty(final ICVSResource cvsResource, IProgressMonitor monitor) throws CVSException { 403 if (cvsResource.exists()) 404 return !cvsResource.isIgnored() && cvsResource.isModified(monitor); 405 return cvsResource.isManaged() && cvsResource.isModified(monitor); 406 } 407 408 public boolean isDirty(IResource resource, IProgressMonitor monitor) throws CVSException { 409 try { 410 ICVSResource cvsResource = CVSWorkspaceRoot.getCVSResourceFor(resource); 411 return isDirty(cvsResource, monitor); 412 } catch (CVSException e) { 413 boolean accessible = resource.getProject().isAccessible(); 415 if (accessible) { 416 throw e; 417 } 418 return accessible; 420 } 421 422 } 423 424 public Object getAdapter(Class adapter) { 425 if (adapter == ActiveChangeSetManager.class) { 426 return CVSProviderPlugin.getPlugin().getChangeSetManager(); 427 } 428 return super.getAdapter(adapter); 429 } 430 431 public void refreshWithContentFetch(ResourceTraversal[] traversals, IProgressMonitor monitor) throws TeamException { 432 try { 433 contentFetch = true; 434 refresh(traversals, monitor); 435 } finally { 436 contentFetch = false; 437 } 438 } 439 440 protected boolean getCacheFileContentsHint() { 441 return contentFetch; 442 } 443 } 444 | Popular Tags |