1 11 package org.eclipse.team.internal.ccvs.ui.mappings; 12 13 import java.util.*; 14 15 import org.eclipse.core.resources.*; 16 import org.eclipse.core.runtime.*; 17 import org.eclipse.core.runtime.jobs.ISchedulingRule; 18 import org.eclipse.team.core.Team; 19 import org.eclipse.team.core.diff.IDiff; 20 import org.eclipse.team.core.diff.IThreeWayDiff; 21 import org.eclipse.team.core.mapping.*; 22 import org.eclipse.team.core.mapping.provider.MergeStatus; 23 import org.eclipse.team.core.mapping.provider.ResourceDiffTree; 24 import org.eclipse.team.core.subscribers.Subscriber; 25 import org.eclipse.team.core.subscribers.SubscriberMergeContext; 26 import org.eclipse.team.internal.ccvs.core.*; 27 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; 28 import org.eclipse.team.internal.ccvs.core.resources.EclipseSynchronizer; 29 import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; 30 import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin; 31 import org.eclipse.team.internal.ccvs.ui.Policy; 32 import org.eclipse.team.internal.core.mapping.DelegatingStorageMerger; 33 34 public abstract class CVSSubscriberMergeContext extends SubscriberMergeContext { 35 36 private static final IStorageMerger MERGER = new DelegatingStorageMerger() { 37 protected IStorageMerger findMerger(IStorage target) throws CoreException { 38 IStorageMerger storageMerger = super.findMerger(target); 39 if (storageMerger == null) { 40 if (target instanceof IFile) { 41 IFile file = (IFile) target; 42 if (isText(file)) 43 storageMerger = getTextMerger(); 44 } 45 } 46 return storageMerger; 47 } 48 49 protected int getType(IStorage target) { 50 if (target instanceof IFile) { 51 IFile file = (IFile) target; 52 if (isText(file)) 53 return Team.TEXT; 54 return Team.BINARY; 55 } 56 return super.getType(target); 57 } 58 59 private boolean isText(IFile file) { 60 try { 61 ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor(file); 62 byte[] syncBytes = cvsFile.getSyncBytes(); 63 if (syncBytes != null) 64 return !ResourceSyncInfo.isBinary(syncBytes); 65 } catch (CVSException e) { 66 CVSUIPlugin.log(e); 67 } 68 return false; 69 } 70 }; 71 72 protected CVSSubscriberMergeContext(Subscriber subscriber, ISynchronizationScopeManager manager) { 73 super(subscriber, manager); 74 } 75 76 79 public void run(final IWorkspaceRunnable runnable, final ISchedulingRule rule, int flags, IProgressMonitor monitor) throws CoreException { 80 super.run(new IWorkspaceRunnable() { 81 public void run(IProgressMonitor monitor) throws CoreException { 82 EclipseSynchronizer.getInstance().run(rule, new ICVSRunnable(){ 83 public void run(IProgressMonitor monitor) throws CVSException { 84 try { 85 runnable.run(monitor); 86 } catch (CoreException e) { 87 throw CVSException.wrapException(e); 88 } 89 } 90 }, monitor); 91 } 92 93 }, rule, flags, monitor); 94 } 95 96 99 public ISchedulingRule getMergeRule(IDiff node) { 100 return getDiffTree().getResource(node).getProject(); 102 } 103 104 107 protected void makeInSync(IDiff diff, IProgressMonitor monitor) throws CoreException { 108 markAsMerged(diff, true, monitor); 109 } 110 111 114 public void reject(IDiff diff, IProgressMonitor monitor) throws CoreException { 115 markAsMerged(diff, false, monitor); 116 } 117 118 public IStatus merge(final IDiff[] diffs, final boolean ignoreLocalChanges, IProgressMonitor monitor) throws CoreException { 119 final IStatus[] result = new IStatus[] { Status.OK_STATUS }; 120 if (diffs.length > 0) 121 run(new IWorkspaceRunnable() { 122 public void run(IProgressMonitor monitor) throws CoreException { 123 result[0] = internalMerge(diffs, ignoreLocalChanges, monitor); 124 } 125 }, getMergeRule(diffs), IWorkspace.AVOID_UPDATE, monitor); 126 return result[0]; 127 } 128 129 private IStatus internalMerge(final IDiff[] diffs, final boolean ignoreLocalChanges, IProgressMonitor monitor) throws CoreException { 130 131 List fileChanges = new ArrayList(); 133 List folderDiffs = new ArrayList(); 135 List fileDeletions = new ArrayList(); 138 139 for (int i = 0; i < diffs.length; i++) { 140 IDiff diff = diffs[i]; 141 IResource resource = ResourceDiffTree.getResourceFor(diff); 142 if (resource.getType() == IResource.FILE) { 143 if (isIncomingDeletion(diff, ignoreLocalChanges)) { 144 fileDeletions.add(diff); 145 } else { 146 fileChanges.add(diff); 147 } 148 } else { 149 folderDiffs.add(diff); 150 } 151 } 152 153 if (fileDeletions.isEmpty() && fileChanges.isEmpty() && folderDiffs.isEmpty()) 154 return Status.OK_STATUS; 155 156 int ticks = (fileDeletions.size() + fileChanges.size()) * 100; 158 try { 159 monitor.beginTask(null, ticks); 160 List result = new ArrayList(); 161 if (!fileDeletions.isEmpty()) { 162 IStatus status = CVSSubscriberMergeContext.super.merge( 163 (IDiff[]) fileDeletions.toArray(new IDiff[fileDeletions.size()]), 164 ignoreLocalChanges, 165 Policy.subMonitorFor(monitor, 100 * fileDeletions.size())); 166 if (!status.isOK()) { 167 if (status.isMultiStatus()) { 168 result.addAll(Arrays.asList(status.getChildren())); 169 } else { 170 result.add(status); 171 } 172 } 173 } 174 if (!fileChanges.isEmpty()) { 175 IStatus status = CVSSubscriberMergeContext.super.merge( 176 (IDiff[]) fileChanges.toArray(new IDiff[fileChanges.size()]), 177 ignoreLocalChanges, 178 Policy.subMonitorFor(monitor, 100 * fileChanges.size())); 179 if (!status.isOK()) { 180 if (status.isMultiStatus()) { 181 result.addAll(Arrays.asList(status.getChildren())); 182 } else { 183 result.add(status); 184 } 185 } 186 } 187 if (!folderDiffs.isEmpty()) { 188 Collections.sort(folderDiffs, new Comparator() { 190 public int compare(Object o1, Object o2) { 191 return ((IDiff)o2).getPath().toString().compareTo(((IDiff)o1).getPath().toString()); 192 } 193 }); 194 for (Iterator iter = folderDiffs.iterator(); iter.hasNext();) { 195 IDiff diff = (IDiff) iter.next(); 196 IResource resource = ResourceDiffTree.getResourceFor(diff); 197 IDiff currentDiff = getSubscriber().getDiff(resource); 198 merge(currentDiff, ignoreLocalChanges, monitor); 199 } 200 } 201 if (result.isEmpty()) 202 return Status.OK_STATUS; 203 if (result.size() == 1) 204 return (IStatus)result.get(0); 205 return new MergeStatus(CVSUIPlugin.ID, ((IStatus)result.get(0)).getMessage(), getFailedFiles(result)); 206 } finally { 207 monitor.done(); 208 } 209 } 210 211 private boolean isIncomingDeletion(IDiff diff, boolean ignoreLocalChanges) { 212 if (diff instanceof IThreeWayDiff) { 213 IThreeWayDiff twd = (IThreeWayDiff) diff; 214 if (twd.getKind() == IDiff.REMOVE && twd.getDirection() == IThreeWayDiff.INCOMING) 215 return true; 216 IDiff remoteChange = twd.getRemoteChange(); 217 if (ignoreLocalChanges && remoteChange != null) 218 return isIncomingDeletion(remoteChange, ignoreLocalChanges); 219 IDiff localChange = twd.getLocalChange(); 220 if (ignoreLocalChanges && localChange != null) 221 return isIncomingDeletion(localChange, ignoreLocalChanges); 222 return false; 223 } 224 if (diff instanceof IResourceDiff) { 225 IResourceDiff rd = (IResourceDiff) diff; 226 return (ignoreLocalChanges || getMergeType() == ISynchronizationContext.TWO_WAY) && rd.getAfterState() == null; 227 } 228 return false; 229 } 230 231 private IFile[] getFailedFiles(List result) { 232 List failures = new ArrayList(); 233 for (Iterator iter = result.iterator(); iter.hasNext();) { 234 IStatus status = (IStatus) iter.next(); 235 if (status instanceof MergeStatus) { 236 MergeStatus ms = (MergeStatus) status; 237 failures.addAll(Arrays.asList(ms.getConflictingFiles())); 238 } 239 } 240 return (IFile[]) failures.toArray(new IFile[failures.size()]); 241 } 242 243 public Object getAdapter(Class adapter) { 244 if (adapter == IStorageMerger.class) 245 return MERGER; 246 return super.getAdapter(adapter); 247 } 248 249 } 250 | Popular Tags |