1 11 package org.eclipse.team.internal.ccvs.ui.subscriber; 12 13 import java.lang.reflect.InvocationTargetException ; 14 import java.util.ArrayList ; 15 import java.util.HashSet ; 16 import java.util.List ; 17 import java.util.Set ; 18 19 import org.eclipse.compare.structuremergeviewer.IDiffElement; 20 import org.eclipse.core.resources.*; 21 import org.eclipse.core.runtime.IProgressMonitor; 22 import org.eclipse.jface.dialogs.MessageDialog; 23 import org.eclipse.osgi.util.NLS; 24 import org.eclipse.team.core.TeamException; 25 import org.eclipse.team.core.synchronize.FastSyncInfoFilter; 26 import org.eclipse.team.core.synchronize.SyncInfo; 27 import org.eclipse.team.core.synchronize.SyncInfoSet; 28 import org.eclipse.team.core.synchronize.FastSyncInfoFilter.AndSyncInfoFilter; 29 import org.eclipse.team.core.synchronize.FastSyncInfoFilter.OrSyncInfoFilter; 30 import org.eclipse.team.core.synchronize.FastSyncInfoFilter.SyncInfoDirectionFilter; 31 import org.eclipse.team.core.variants.IResourceVariant; 32 import org.eclipse.team.internal.ccvs.core.CVSException; 33 import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin; 34 import org.eclipse.team.internal.ccvs.core.ICVSFile; 35 import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption; 36 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; 37 import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; 38 import org.eclipse.team.internal.ccvs.ui.*; 39 import org.eclipse.team.internal.ccvs.ui.operations.UpdateOnlyMergableOperation; 40 import org.eclipse.team.internal.ui.TeamUIPlugin; 41 import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; 42 43 50 public abstract class SafeUpdateOperation extends CVSSubscriberOperation { 51 52 private boolean promptBeforeUpdate = false; 53 54 private SyncInfoSet skipped = new SyncInfoSet(); 55 56 protected SafeUpdateOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements, boolean promptBeforeUpdate) { 57 super(configuration, elements); 58 this.promptBeforeUpdate = promptBeforeUpdate; 59 } 60 61 64 public boolean shouldRun() { 65 return promptIfNeeded(); 66 } 67 68 71 public void run(IProgressMonitor monitor) throws InvocationTargetException , InterruptedException { 72 skipped.clear(); 73 super.run(monitor); 74 try { 75 handleFailedUpdates(monitor); 76 } catch (TeamException e) { 77 throw new InvocationTargetException (e); 78 } 79 } 80 81 84 public void runWithProjectRule(IProject project, SyncInfoSet syncSet, IProgressMonitor monitor) throws TeamException { 85 try { 86 monitor.beginTask(null, 100); 87 88 removeKnownFailureCases(syncSet); 90 91 safeUpdate(project, syncSet, Policy.subMonitorFor(monitor, 100)); 94 95 syncSet.rejectNodes(new FastSyncInfoFilter() { 97 public boolean select(SyncInfo info) { 98 return skipped.getSyncInfo(info.getLocal()) != null; 99 } 100 }); 101 102 updated(syncSet.getResources()); 104 } finally { 105 monitor.done(); 106 } 107 } 108 109 113 private SyncInfoSet removeKnownFailureCases(SyncInfoSet syncSet) { 114 FastSyncInfoFilter failFilter = getKnownFailureCases(); 116 SyncInfo[] willFail = syncSet.getNodes(failFilter); 117 syncSet.rejectNodes(failFilter); 118 for (int i = 0; i < willFail.length; i++) { 119 SyncInfo info = willFail[i]; 120 skipped.add(info); 121 } 122 return syncSet; 123 } 124 125 private void handleFailedUpdates(IProgressMonitor monitor) throws TeamException { 126 if(! skipped.isEmpty()) { 128 if(getOverwriteLocalChanges()) { 129 if(promptForOverwrite(skipped)) { 131 overwriteUpdate(skipped, monitor); 132 if (!skipped.isEmpty()) { 133 updated(skipped.getResources()); 134 } 135 } 136 } else { 137 warnAboutFailedResources(skipped); 140 } 141 } 142 } 143 144 protected boolean getOverwriteLocalChanges(){ 145 return false; 146 } 147 148 154 protected void safeUpdate(IProject project, SyncInfoSet syncSet, IProgressMonitor monitor) throws TeamException { 155 SyncInfo[] changed = syncSet.getSyncInfos(); 156 if (changed.length == 0) return; 157 158 List updateShallow = new ArrayList (); 160 Set parentCreationElements = new HashSet (); 163 List updateDeletions = new ArrayList (); 166 167 for (int i = 0; i < changed.length; i++) { 168 SyncInfo changedNode = changed[i]; 169 170 SyncInfo parent = getParent(changedNode); 172 if (parent != null && isOutOfSync(parent)) { 173 parentCreationElements.add(parent); 176 } 177 178 IResource resource = changedNode.getLocal(); 179 int kind = changedNode.getKind(); 180 boolean willBeAttempted = false; 181 if (resource.getType() == IResource.FILE) { 182 switch (kind & SyncInfo.DIRECTION_MASK) { 185 case SyncInfo.INCOMING: 186 switch (kind & SyncInfo.CHANGE_MASK) { 187 case SyncInfo.DELETION: 188 updateDeletions.add(changedNode); 190 willBeAttempted = true; 191 break; 192 default: 193 updateShallow.add(changedNode); 195 willBeAttempted = true; 196 break; 197 } 198 break; 199 case SyncInfo.CONFLICTING: 200 switch (kind & SyncInfo.CHANGE_MASK) { 201 case SyncInfo.CHANGE: 202 updateShallow.add(changedNode); 204 willBeAttempted = true; 205 break; 206 } 207 break; 208 } 209 if (!willBeAttempted) { 210 skipped.add(syncSet.getSyncInfo(resource)); 211 } 212 } else { 213 if (isOutOfSync(changedNode)) { 217 parentCreationElements.add(changedNode); 218 } 219 } 220 221 } 222 try { 223 monitor.beginTask(null, 100); 224 225 if (updateDeletions.size() > 0) { 226 runUpdateDeletions((SyncInfo[])updateDeletions.toArray(new SyncInfo[updateDeletions.size()]), Policy.subMonitorFor(monitor, 25)); 227 } 228 if (parentCreationElements.size() > 0) { 229 makeInSync((SyncInfo[]) parentCreationElements.toArray(new SyncInfo[parentCreationElements.size()]), Policy.subMonitorFor(monitor, 25)); 230 } 231 if (updateShallow.size() > 0) { 232 runSafeUpdate(project, (SyncInfo[])updateShallow.toArray(new SyncInfo[updateShallow.size()]), Policy.subMonitorFor(monitor, 50)); 233 } 234 } finally { 235 monitor.done(); 236 } 237 return; 238 } 239 240 248 protected abstract void overwriteUpdate(SyncInfoSet syncSet, IProgressMonitor monitor) throws TeamException; 249 250 254 protected FastSyncInfoFilter getKnownFailureCases() { 255 return new OrSyncInfoFilter(new FastSyncInfoFilter[] { 256 new AndSyncInfoFilter(new FastSyncInfoFilter[] { 258 FastSyncInfoFilter.getDirectionAndChangeFilter(SyncInfo.CONFLICTING, SyncInfo.ADDITION), 259 new FastSyncInfoFilter() { 260 public boolean select(SyncInfo info) { 261 return info.getLocal().getType() == IResource.FILE; 262 } 263 } 264 }), 265 new AndSyncInfoFilter(new FastSyncInfoFilter[] { 268 FastSyncInfoFilter.getDirectionAndChangeFilter(SyncInfo.CONFLICTING, SyncInfo.CHANGE), 269 new FastSyncInfoFilter() { 270 public boolean select(SyncInfo info) { 271 if (info.getLocal().getType() == IResource.FILE) { 272 try { 273 ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor((IFile)info.getLocal()); 274 byte[] syncBytes = cvsFile.getSyncBytes(); 275 return (syncBytes == null || ResourceSyncInfo.isAddition(syncBytes)); 276 } catch (CVSException e) { 277 CVSUIPlugin.log(e); 278 } 280 } 281 return false; 282 } 283 } 284 }), 285 new AndSyncInfoFilter(new FastSyncInfoFilter[] { 287 FastSyncInfoFilter.getDirectionAndChangeFilter(SyncInfo.CONFLICTING, SyncInfo.CHANGE), 288 new FastSyncInfoFilter() { 289 public boolean select(SyncInfo info) { 290 IResourceVariant remote = info.getRemote(); 291 IResourceVariant base = info.getBase(); 292 if (info.getLocal().exists()) { 293 return (base != null && remote == null); 295 } else { 296 return (base != null && remote != null && !base.equals(remote)); 298 } 299 } 300 } 301 }), 302 new AndSyncInfoFilter(new FastSyncInfoFilter[] { 305 FastSyncInfoFilter.getDirectionAndChangeFilter(SyncInfo.CONFLICTING, SyncInfo.CHANGE), 306 new FastSyncInfoFilter() { 307 public boolean select(SyncInfo info) { 308 IResource local = info.getLocal(); 309 if (local.getType() == IResource.FILE) { 310 try { 311 ICVSFile file = CVSWorkspaceRoot.getCVSFileFor((IFile)local); 312 byte[] syncBytes = file.getSyncBytes(); 313 if (syncBytes != null) { 314 return ResourceSyncInfo.isBinary(syncBytes); 315 } 316 } catch (CVSException e) { 317 CVSProviderPlugin.log(e); 320 return true; 321 } 322 } 323 return false; 324 } 325 } 326 }), 327 new SyncInfoDirectionFilter(SyncInfo.OUTGOING) 329 }); 330 } 331 332 336 protected void warnAboutFailedResources(final SyncInfoSet syncSet) { 337 TeamUIPlugin.getStandardDisplay().syncExec(new Runnable () { 338 public void run() { 339 MessageDialog.openInformation(getShell(), 340 CVSUIMessages.SafeUpdateAction_warnFilesWithConflictsTitle, 341 CVSUIMessages.SafeUpdateAction_warnFilesWithConflictsDescription); 342 } 343 }); 344 } 345 346 354 protected abstract void runUpdateDeletions(SyncInfo[] nodes, IProgressMonitor monitor) throws TeamException; 355 356 365 protected abstract void runSafeUpdate(IProject project, SyncInfo[] nodes, IProgressMonitor monitor) throws TeamException; 366 367 protected void safeUpdate(IProject project, IResource[] resources, LocalOption[] localOptions, IProgressMonitor monitor) throws TeamException { 368 try { 369 UpdateOnlyMergableOperation operation = new UpdateOnlyMergableOperation(getPart(), project, resources, localOptions); 370 operation.run(monitor); 371 addSkippedFiles(operation.getSkippedFiles()); 372 } catch (InvocationTargetException e) { 373 throw CVSException.wrapException(e); 374 } catch (InterruptedException e) { 375 Policy.cancelOperation(); 376 } 377 } 378 379 382 protected abstract void updated(IResource[] resources) throws TeamException; 383 384 private void addSkippedFiles(IFile[] files) { 385 SyncInfoSet set = getSyncInfoSet(); 386 for (int i = 0; i < files.length; i++) { 387 IFile file = files[i]; 388 skipped.add(set.getSyncInfo(file)); 389 } 390 } 391 392 protected String getErrorTitle() { 393 return CVSUIMessages.UpdateAction_update; 394 } 395 396 399 protected String getJobName() { 400 SyncInfoSet syncSet = getSyncInfoSet(); 401 return NLS.bind(CVSUIMessages.UpdateAction_jobName, new String [] { new Integer (syncSet.size()).toString() }); 402 } 403 404 412 private boolean promptIfNeeded() { 413 final SyncInfoSet set = getSyncInfoSet(); 414 final boolean[] result = new boolean[] {true}; 415 if(getPromptBeforeUpdate()) { 416 TeamUIPlugin.getStandardDisplay().syncExec(new Runnable () { 417 public void run() { 418 String sizeString = Integer.toString(set.size()); 419 String message = set.size() > 1 ? NLS.bind(CVSUIMessages.UpdateAction_promptForUpdateSeveral, new String [] { sizeString }) : NLS.bind(CVSUIMessages.UpdateAction_promptForUpdateOne, new String [] { sizeString }); result[0] = MessageDialog.openQuestion(getShell(), NLS.bind(CVSUIMessages.UpdateAction_promptForUpdateTitle, new String [] { sizeString }), message); 421 } 422 }); 423 } 424 return result[0]; 425 } 426 427 public boolean getPromptBeforeUpdate() { 428 return promptBeforeUpdate; 429 } 430 } 431 | Popular Tags |