1 11 package org.eclipse.team.core.mapping.provider; 12 13 import java.io.*; 14 import java.util.*; 15 16 import org.eclipse.core.resources.*; 17 import org.eclipse.core.runtime.*; 18 import org.eclipse.core.runtime.jobs.ISchedulingRule; 19 import org.eclipse.core.runtime.jobs.MultiRule; 20 import org.eclipse.osgi.util.NLS; 21 import org.eclipse.team.core.diff.IDiff; 22 import org.eclipse.team.core.diff.IThreeWayDiff; 23 import org.eclipse.team.core.history.IFileRevision; 24 import org.eclipse.team.core.mapping.*; 25 import org.eclipse.team.internal.core.*; 26 import org.eclipse.team.internal.core.mapping.DelegatingStorageMerger; 27 import org.eclipse.team.internal.core.mapping.SyncInfoToDiffConverter; 28 29 39 public abstract class MergeContext extends SynchronizationContext implements IMergeContext { 40 41 45 protected MergeContext(ISynchronizationScopeManager manager, int type, IResourceDiffTree deltaTree) { 46 super(manager, type, deltaTree); 47 } 48 49 52 public void reject(final IDiff[] diffs, IProgressMonitor monitor) throws CoreException { 53 run(new IWorkspaceRunnable() { 54 public void run(IProgressMonitor monitor) throws CoreException { 55 for (int i = 0; i < diffs.length; i++) { 56 IDiff node = diffs[i]; 57 reject(node, monitor); 58 } 59 } 60 }, getMergeRule(diffs), IResource.NONE, monitor); 61 } 62 63 66 public void markAsMerged(final IDiff[] nodes, final boolean inSyncHint, IProgressMonitor monitor) throws CoreException { 67 run(new IWorkspaceRunnable() { 68 public void run(IProgressMonitor monitor) throws CoreException { 69 for (int i = 0; i < nodes.length; i++) { 70 IDiff node = nodes[i]; 71 markAsMerged(node, inSyncHint, monitor); 72 } 73 } 74 }, getMergeRule(nodes), IResource.NONE, monitor); 75 } 76 77 80 public IStatus merge(final IDiff[] deltas, final boolean force, IProgressMonitor monitor) throws CoreException { 81 final List failedFiles = new ArrayList(); 82 run(new IWorkspaceRunnable() { 83 public void run(IProgressMonitor monitor) throws CoreException { 84 try { 85 monitor.beginTask(null, deltas.length * 100); 86 for (int i = 0; i < deltas.length; i++) { 87 IDiff delta = deltas[i]; 88 IStatus s = merge(delta, force, Policy.subMonitorFor(monitor, 100)); 89 if (!s.isOK()) { 90 if (s.getCode() == IMergeStatus.CONFLICTS) { 91 failedFiles.addAll(Arrays.asList(((IMergeStatus)s).getConflictingFiles())); 92 } else { 93 throw new CoreException(s); 94 } 95 } 96 } 97 } finally { 98 monitor.done(); 99 } 100 } 101 }, getMergeRule(deltas), IWorkspace.AVOID_UPDATE, monitor); 102 if (failedFiles.isEmpty()) { 103 return Status.OK_STATUS; 104 } else { 105 return new MergeStatus(TeamPlugin.ID, Messages.MergeContext_0, (IFile[]) failedFiles.toArray(new IFile[failedFiles.size()])); 106 } 107 } 108 109 112 public IStatus merge(IDiff diff, boolean ignoreLocalChanges, IProgressMonitor monitor) throws CoreException { 113 Policy.checkCanceled(monitor); 114 IResource resource = getDiffTree().getResource(diff); 115 if (resource.getType() != IResource.FILE) { 116 if (diff instanceof IThreeWayDiff) { 117 IThreeWayDiff twd = (IThreeWayDiff) diff; 118 if ((ignoreLocalChanges || getMergeType() == TWO_WAY) 119 && resource.getType() == IResource.FOLDER 120 && twd.getKind() == IDiff.ADD 121 && twd.getDirection() == IThreeWayDiff.OUTGOING 122 && ((IFolder)resource).members().length == 0) { 123 ((IFolder)resource).delete(false, monitor); 125 } else if (resource.getType() == IResource.FOLDER 126 && !resource.exists() 127 && twd.getKind() == IDiff.ADD 128 && twd.getDirection() == IThreeWayDiff.INCOMING) { 129 ensureParentsExist(resource, monitor); 130 ((IFolder)resource).create(false, true, monitor); 131 makeInSync(diff, monitor); 132 } 133 } 134 return Status.OK_STATUS; 135 } 136 if (diff instanceof IThreeWayDiff && !ignoreLocalChanges && getMergeType() == THREE_WAY) { 137 IThreeWayDiff twDelta = (IThreeWayDiff) diff; 138 int direction = twDelta.getDirection(); 139 if (direction == IThreeWayDiff.OUTGOING) { 140 return Status.OK_STATUS; 142 } 143 if (direction == IThreeWayDiff.INCOMING) { 144 performReplace(diff, monitor); 146 return Status.OK_STATUS; 147 } 148 int type = twDelta.getKind(); 150 if (type == IDiff.REMOVE) { 151 makeInSync(diff, monitor); 152 return Status.OK_STATUS; 153 } 154 IResourceDiff remoteChange = (IResourceDiff)twDelta.getRemoteChange(); 156 IFileRevision remote = null; 157 if (remoteChange != null) { 158 remote = remoteChange.getAfterState(); 159 } 160 if (remote == null || !getLocalFile(diff).exists()) { 161 return new MergeStatus(TeamPlugin.ID, NLS.bind(Messages.MergeContext_1, new String [] { diff.getPath().toString() }), new IFile[] { getLocalFile(diff) }); 164 } 165 return performThreeWayMerge(twDelta, monitor); 168 } else { 169 performReplace(diff, monitor); 170 return Status.OK_STATUS; 171 } 172 173 } 174 175 186 protected IStatus performThreeWayMerge(final IThreeWayDiff diff, IProgressMonitor monitor) throws CoreException { 187 final IStatus[] result = new IStatus[] { Status.OK_STATUS }; 188 run(new IWorkspaceRunnable() { 189 public void run(IProgressMonitor monitor) throws CoreException { 190 monitor.beginTask(null, 100); 191 IResourceDiff localDiff = (IResourceDiff)diff.getLocalChange(); 192 IResourceDiff remoteDiff = (IResourceDiff)diff.getRemoteChange(); 193 IStorageMerger merger = (IStorageMerger)getAdapter(IStorageMerger.class); 194 if (merger == null) 195 merger = DelegatingStorageMerger.getInstance(); 196 IFile file = (IFile)localDiff.getResource(); 197 monitor.subTask(NLS.bind(Messages.MergeContext_5, file.getFullPath().toString())); 198 String osEncoding = file.getCharset(); 199 IFileRevision ancestorState = localDiff.getBeforeState(); 200 IFileRevision remoteState = remoteDiff.getAfterState(); 201 IStorage ancestorStorage; 202 if (ancestorState != null) 203 ancestorStorage = ancestorState.getStorage(Policy.subMonitorFor(monitor, 30)); 204 else 205 ancestorStorage = null; 206 IStorage remoteStorage = remoteState.getStorage(Policy.subMonitorFor(monitor, 30)); 207 OutputStream os = getTempOutputStream(file); 208 try { 209 IStatus status = merger.merge(os, osEncoding, ancestorStorage, file, remoteStorage, Policy.subMonitorFor(monitor, 30)); 210 if (status.isOK()) { 211 file.setContents(getTempInputStream(file, os), false, true, Policy.subMonitorFor(monitor, 5)); 212 markAsMerged(diff, false, Policy.subMonitorFor(monitor, 5)); 213 } else { 214 status = new MergeStatus(status.getPlugin(), status.getMessage(), new IFile[]{file}); 215 } 216 result[0] = status; 217 } finally { 218 disposeTempOutputStream(file, os); 219 } 220 monitor.done(); 221 } 222 }, getMergeRule(diff), IWorkspace.AVOID_UPDATE, monitor); 223 return result[0]; 224 } 225 226 private void disposeTempOutputStream(IFile file, OutputStream output) { 227 if (output instanceof ByteArrayOutputStream) 228 return; 229 try { 231 if (output != null) 234 output.close(); 235 } catch (IOException e) { 236 } 238 File tmpFile = getTempFile(file); 239 if (tmpFile.exists()) 240 tmpFile.delete(); 241 } 242 243 private OutputStream getTempOutputStream(IFile file) throws CoreException { 244 File tmpFile = getTempFile(file); 245 if (tmpFile.exists()) 246 tmpFile.delete(); 247 File parent = tmpFile.getParentFile(); 248 if (!parent.exists()) 249 parent.mkdirs(); 250 try { 251 return new BufferedOutputStream(new FileOutputStream(tmpFile)); 252 } catch (FileNotFoundException e) { 253 TeamPlugin.log(IStatus.ERROR, NLS.bind("Could not open temporary file {0} for writing: {1}", new String [] { tmpFile.getAbsolutePath(), e.getMessage() }), e); return new ByteArrayOutputStream(); 255 } 256 } 257 258 private InputStream getTempInputStream(IFile file, OutputStream output) throws CoreException { 259 if (output instanceof ByteArrayOutputStream) { 260 ByteArrayOutputStream baos = (ByteArrayOutputStream) output; 261 return new ByteArrayInputStream(baos.toByteArray()); 262 } 263 try { 265 if (output != null) 267 output.close(); 268 } catch (IOException e) { 269 } 271 File tmpFile = getTempFile(file); 272 try { 273 return new BufferedInputStream(new FileInputStream(tmpFile)); 274 } catch (FileNotFoundException e) { 275 throw new CoreException(new Status(IStatus.ERROR, TeamPlugin.ID, IMergeStatus.INTERNAL_ERROR, NLS.bind(Messages.MergeContext_4, new String [] { tmpFile.getAbsolutePath(), e.getMessage() }), e)); 276 } 277 } 278 279 private File getTempFile(IFile file) { 280 return TeamPlugin.getPlugin().getStateLocation().append(".tmp").append(file.getName() + ".tmp").toFile(); } 282 283 private IFile getLocalFile(IDiff delta) { 284 return ResourcesPlugin.getWorkspace().getRoot().getFile(delta.getPath()); 285 } 286 287 303 protected void performReplace(final IDiff diff, IProgressMonitor monitor) throws CoreException { 304 IResourceDiff d; 305 IFile file = getLocalFile(diff); 306 IFileRevision remote = null; 307 if (diff instanceof IResourceDiff) { 308 d = (IResourceDiff) diff; 309 if (d != null) 310 remote = d.getAfterState(); 311 } else { 312 d = (IResourceDiff)((IThreeWayDiff)diff).getRemoteChange(); 313 if (d != null) 314 remote = d.getAfterState(); 315 } 316 if (d == null) { 317 d = (IResourceDiff)((IThreeWayDiff)diff).getLocalChange(); 318 if (d != null) 319 remote = d.getBeforeState(); 320 } 321 322 if (d != null) { 324 performReplace(diff, file, remote, monitor); 325 } 326 } 327 328 344 protected abstract void makeInSync(IDiff diff, IProgressMonitor monitor) throws CoreException; 345 346 private void performReplace(final IDiff diff, final IFile file, final IFileRevision remote, IProgressMonitor monitor) throws CoreException { 347 run(new IWorkspaceRunnable() { 348 public void run(IProgressMonitor monitor) throws CoreException { 349 try { 350 monitor.beginTask(null, 100); 351 monitor.subTask(NLS.bind(Messages.MergeContext_6, file.getFullPath().toString())); 352 if ((remote == null || !remote.exists()) && file.exists()) { 353 file.delete(false, true, Policy.subMonitorFor(monitor, 95)); 354 } else if (remote != null) { 355 ensureParentsExist(file, monitor); 356 InputStream stream = remote.getStorage(monitor).getContents(); 357 stream = new BufferedInputStream(stream); 358 try { 359 if (file.exists()) { 360 file.setContents(stream, false, true, Policy.subMonitorFor(monitor, 95)); 361 } else { 362 file.create(stream, false, Policy.subMonitorFor(monitor, 95)); 363 } 364 } finally { 365 try { 366 stream.close(); 367 } catch (IOException e) { 368 } 370 } 371 } 372 makeInSync(diff, Policy.subMonitorFor(monitor, 5)); 374 } finally { 375 monitor.done(); 376 } 377 } 378 }, getMergeRule(diff), IWorkspace.AVOID_UPDATE, monitor); 379 } 380 381 392 protected void ensureParentsExist(IResource resource, IProgressMonitor monitor) throws CoreException { 393 IContainer parent = resource.getParent(); 394 if (parent.getType() != IResource.FOLDER) { 395 return; 397 } 398 if (!parent.exists()) { 399 ensureParentsExist(parent, monitor); 400 ((IFolder)parent).create(false, true, monitor); 401 } 402 } 403 404 409 public void run(IWorkspaceRunnable runnable, ISchedulingRule rule, int flags, IProgressMonitor monitor) throws CoreException { 410 ResourcesPlugin.getWorkspace().run(runnable, rule, flags, monitor); 411 } 412 413 418 public ISchedulingRule getMergeRule(IDiff diff) { 419 IResource resource = getDiffTree().getResource(diff); 420 IResourceRuleFactory ruleFactory = ResourcesPlugin.getWorkspace().getRuleFactory(); 421 ISchedulingRule rule; 422 if (!resource.exists()) { 423 rule = ruleFactory.createRule(resource); 424 } else if (SyncInfoToDiffConverter.getRemote(diff) == null){ 425 rule = ruleFactory.deleteRule(resource); 426 } else { 427 rule = ruleFactory.modifyRule(resource); 428 } 429 return rule; 430 } 431 432 435 public ISchedulingRule getMergeRule(IDiff[] deltas) { 436 ISchedulingRule result = null; 437 for (int i = 0; i < deltas.length; i++) { 438 IDiff node = deltas[i]; 439 ISchedulingRule rule = getMergeRule(node); 440 if (result == null) { 441 result = rule; 442 } else { 443 result = MultiRule.combine(result, rule); 444 } 445 } 446 return result; 447 } 448 449 452 public int getMergeType() { 453 return getType(); 454 } 455 456 public Object getAdapter(Class adapter) { 457 if (adapter == IStorageMerger.class) { 458 return DelegatingStorageMerger.getInstance(); 459 } 460 return super.getAdapter(adapter); 461 } 462 } 463 | Popular Tags |