1 /******************************************************************************* 2 * Copyright (c) 2000, 2017 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.team.internal.core.mapping; 15 16 import org.eclipse.core.resources.IFile; 17 import org.eclipse.core.resources.IResource; 18 import org.eclipse.core.runtime.IAdaptable; 19 import org.eclipse.osgi.util.NLS; 20 import org.eclipse.team.core.TeamException; 21 import org.eclipse.team.core.diff.IDiff; 22 import org.eclipse.team.core.diff.IThreeWayDiff; 23 import org.eclipse.team.core.diff.ITwoWayDiff; 24 import org.eclipse.team.core.diff.provider.Diff; 25 import org.eclipse.team.core.diff.provider.ThreeWayDiff; 26 import org.eclipse.team.core.history.IFileRevision; 27 import org.eclipse.team.core.mapping.IResourceDiff; 28 import org.eclipse.team.core.mapping.provider.ResourceDiff; 29 import org.eclipse.team.core.synchronize.SyncInfo; 30 import org.eclipse.team.core.variants.IResourceVariant; 31 import org.eclipse.team.core.variants.IResourceVariantComparator; 32 import org.eclipse.team.internal.core.Messages; 33 import org.eclipse.team.internal.core.history.LocalFileRevision; 34 35 /** 36 * Covert a SyncInfo into a IDiff 37 */ 38 public class SyncInfoToDiffConverter { 39 40 private static class PrecalculatedSyncInfo extends SyncInfo { 41 public int kind; PrecalculatedSyncInfo(int kind, IResource local, IResourceVariant base, IResourceVariant remote, IResourceVariantComparator comparator)42 public PrecalculatedSyncInfo(int kind, IResource local, IResourceVariant base, IResourceVariant remote, IResourceVariantComparator comparator) { 43 super(local, base, remote, comparator); 44 this.kind = kind; 45 } 46 47 @Override calculateKind()48 protected int calculateKind() throws TeamException { 49 return kind; 50 } 51 } 52 53 private static SyncInfoToDiffConverter instance; 54 55 diffKindToString(int kind)56 public static String diffKindToString(int kind) { 57 String label = ""; //$NON-NLS-1$ 58 if(kind==IDiff.NO_CHANGE) { 59 label = Messages.RemoteSyncElement_insync; 60 } else { 61 switch(kind) { 62 case IDiff.CHANGE: label = Messages.RemoteSyncElement_change ; break; 63 case IDiff.ADD: label = Messages.RemoteSyncElement_addition; break; 64 case IDiff.REMOVE: label = Messages.RemoteSyncElement_deletion; break; 65 } 66 } 67 return label; 68 } 69 diffDirectionToString(int direction)70 public static String diffDirectionToString(int direction) { 71 switch(direction) { 72 case IThreeWayDiff.CONFLICTING: return Messages.RemoteSyncElement_conflicting; 73 case IThreeWayDiff.OUTGOING: return Messages.RemoteSyncElement_outgoing; 74 case IThreeWayDiff.INCOMING: return Messages.RemoteSyncElement_incoming; 75 } 76 return ""; //$NON-NLS-1$ 77 } 78 diffStatusToString(int status)79 public static String diffStatusToString(int status) { 80 int kind = status & Diff.KIND_MASK; 81 String label = diffKindToString(kind); 82 int direction = status & ThreeWayDiff.DIRECTION_MASK; 83 if (direction != 0) 84 label = NLS.bind(Messages.concatStrings, new String[] { diffDirectionToString(direction), label }); 85 return label; 86 } 87 asDiffFlags(int syncInfoFlags)88 public static int asDiffFlags(int syncInfoFlags) { 89 if (syncInfoFlags == SyncInfo.IN_SYNC) 90 return IDiff.NO_CHANGE; 91 int kind = SyncInfo.getChange(syncInfoFlags); 92 int diffFlags = 0; 93 switch (kind) { 94 case SyncInfo.ADDITION: 95 diffFlags = IDiff.ADD; 96 break; 97 case SyncInfo.DELETION: 98 diffFlags = IDiff.REMOVE; 99 break; 100 case SyncInfo.CHANGE: 101 diffFlags = IDiff.CHANGE; 102 break; 103 } 104 int direction = SyncInfo.getDirection(syncInfoFlags); 105 switch (direction) { 106 case SyncInfo.INCOMING: 107 diffFlags |= IThreeWayDiff.INCOMING; 108 break; 109 case SyncInfo.OUTGOING: 110 diffFlags |= IThreeWayDiff.OUTGOING; 111 break; 112 case SyncInfo.CONFLICTING: 113 diffFlags |= IThreeWayDiff.CONFLICTING; 114 break; 115 } 116 return diffFlags; 117 } 118 asSyncInfoKind(IThreeWayDiff diff)119 private static int asSyncInfoKind(IThreeWayDiff diff) { 120 int kind = diff.getKind(); 121 if (diff.getKind() == IDiff.NO_CHANGE) 122 return SyncInfo.IN_SYNC; 123 int syncKind = 0; 124 switch (kind) { 125 case IDiff.ADD: 126 syncKind = SyncInfo.ADDITION; 127 break; 128 case IDiff.REMOVE: 129 syncKind = SyncInfo.DELETION; 130 break; 131 case IDiff.CHANGE: 132 syncKind = SyncInfo.CHANGE; 133 break; 134 } 135 int direction = diff.getDirection(); 136 switch (direction) { 137 case IThreeWayDiff.INCOMING: 138 syncKind |= SyncInfo.INCOMING; 139 break; 140 case IThreeWayDiff.OUTGOING: 141 syncKind |= SyncInfo.OUTGOING; 142 break; 143 case IThreeWayDiff.CONFLICTING: 144 syncKind |= SyncInfo.CONFLICTING; 145 break; 146 } 147 return syncKind; 148 } 149 getDeltaFor(SyncInfo info)150 public IDiff getDeltaFor(SyncInfo info) { 151 if (info.getComparator().isThreeWay()) { 152 ITwoWayDiff local = getLocalDelta(info); 153 ITwoWayDiff remote = getRemoteDelta(info); 154 return new ThreeWayDiff(local, remote); 155 } else { 156 if (info.getKind() != SyncInfo.IN_SYNC) { 157 IResourceVariant remote = info.getRemote(); 158 IResource local = info.getLocal(); 159 int kind; 160 if (remote == null) { 161 kind = IDiff.REMOVE; 162 } else if (!local.exists()) { 163 kind = IDiff.ADD; 164 } else { 165 kind = IDiff.CHANGE; 166 } 167 if (local.getType() == IResource.FILE) { 168 IFileRevision after = asFileState(remote); 169 IFileRevision before = getFileRevisionFor((IFile)local); 170 return new ResourceDiff(info.getLocal(), kind, 0, before, after); 171 } 172 // For folders, we don't need file states 173 return new ResourceDiff(info.getLocal(), kind); 174 } 175 return null; 176 } 177 } 178 getRemoteDelta(SyncInfo info)179 private ITwoWayDiff getRemoteDelta(SyncInfo info) { 180 int direction = SyncInfo.getDirection(info.getKind()); 181 if (direction == SyncInfo.INCOMING || direction == SyncInfo.CONFLICTING) { 182 IResourceVariant ancestor = info.getBase(); 183 IResourceVariant remote = info.getRemote(); 184 int kind; 185 if (ancestor == null) { 186 kind = IDiff.ADD; 187 } else if (remote == null) { 188 kind = IDiff.REMOVE; 189 } else { 190 kind = IDiff.CHANGE; 191 } 192 // For folders, we don't need file states 193 if (info.getLocal().getType() == IResource.FILE) { 194 IFileRevision before = asFileState(ancestor); 195 IFileRevision after = asFileState(remote); 196 return new ResourceDiff(info.getLocal(), kind, 0, before, after); 197 } 198 199 return new ResourceDiff(info.getLocal(), kind); 200 } 201 return null; 202 } 203 asFileState(final IResourceVariant variant)204 private IFileRevision asFileState(final IResourceVariant variant) { 205 if (variant == null) 206 return null; 207 return asFileRevision(variant); 208 } 209 getFileRevisionFor(final IFile file)210 private IFileRevision getFileRevisionFor(final IFile file) { 211 return new LocalFileRevision(file); 212 } 213 asFileRevision(final IResourceVariant variant)214 protected ResourceVariantFileRevision asFileRevision(final IResourceVariant variant) { 215 return new ResourceVariantFileRevision(variant); 216 } 217 getLocalDelta(SyncInfo info)218 private ITwoWayDiff getLocalDelta(SyncInfo info) { 219 int direction = SyncInfo.getDirection(info.getKind()); 220 if (direction == SyncInfo.OUTGOING || direction == SyncInfo.CONFLICTING) { 221 IResourceVariant ancestor = info.getBase(); 222 IResource local = info.getLocal(); 223 int kind; 224 if (ancestor == null) { 225 kind = IDiff.ADD; 226 } else if (!local.exists()) { 227 kind = IDiff.REMOVE; 228 } else { 229 kind = IDiff.CHANGE; 230 } 231 if (local.getType() == IResource.FILE) { 232 IFileRevision before = asFileState(ancestor); 233 IFileRevision after = getFileRevisionFor((IFile)local); 234 return new ResourceDiff(info.getLocal(), kind, 0, before, after); 235 } 236 // For folders, we don't need file states 237 return new ResourceDiff(info.getLocal(), kind); 238 239 } 240 return null; 241 } 242 getRemoteVariant(IThreeWayDiff twd)243 public static IResourceVariant getRemoteVariant(IThreeWayDiff twd) { 244 IFileRevision revision = getRemote(twd); 245 if (revision != null) 246 return asResourceVariant(revision); 247 return null; 248 } 249 getBaseVariant(IThreeWayDiff twd)250 public static IResourceVariant getBaseVariant(IThreeWayDiff twd) { 251 IResourceDiff diff = (IResourceDiff)twd.getRemoteChange(); 252 if (diff != null) 253 return asResourceVariant(diff.getBeforeState()); 254 diff = (IResourceDiff)twd.getLocalChange(); 255 if (diff != null) 256 return asResourceVariant(diff.getBeforeState()); 257 return null; 258 } 259 asSyncInfo(IDiff diff, IResourceVariantComparator comparator)260 public SyncInfo asSyncInfo(IDiff diff, IResourceVariantComparator comparator) { 261 if (diff instanceof ResourceDiff) { 262 ResourceDiff rd = (ResourceDiff) diff; 263 IResource local = rd.getResource(); 264 IFileRevision afterState = rd.getAfterState(); 265 IResourceVariant remote = asResourceVariant(afterState); 266 int kind; 267 if (remote == null) { 268 kind = SyncInfo.DELETION; 269 } else if (!local.exists()) { 270 kind = SyncInfo.ADDITION; 271 } else { 272 kind = SyncInfo.CHANGE; 273 } 274 SyncInfo info = createSyncInfo(comparator, kind, local, null, remote); 275 return info; 276 } else if (diff instanceof IThreeWayDiff) { 277 IThreeWayDiff twd = (IThreeWayDiff) diff; 278 IResource local = getLocal(twd); 279 if (local != null) { 280 IResourceVariant remote = getRemoteVariant(twd); 281 IResourceVariant base = getBaseVariant(twd); 282 int kind = asSyncInfoKind(twd); 283 SyncInfo info = createSyncInfo(comparator, kind, local, base, remote); 284 return info; 285 } 286 } 287 return null; 288 } 289 createSyncInfo(IResourceVariantComparator comparator, int kind, IResource local, IResourceVariant base, IResourceVariant remote)290 protected SyncInfo createSyncInfo(IResourceVariantComparator comparator, int kind, IResource local, IResourceVariant base, IResourceVariant remote) { 291 PrecalculatedSyncInfo info = new PrecalculatedSyncInfo(kind, local, base, remote, comparator); 292 try { 293 info.init(); 294 } catch (TeamException e) { 295 // Ignore 296 } 297 return info; 298 } 299 getLocal(IThreeWayDiff twd)300 private static IResource getLocal(IThreeWayDiff twd) { 301 IResourceDiff diff = (IResourceDiff)twd.getRemoteChange(); 302 if (diff != null) 303 return diff.getResource(); 304 diff = (IResourceDiff)twd.getLocalChange(); 305 if (diff != null) 306 return diff.getResource(); 307 return null; 308 } 309 asResourceVariant(IFileRevision revision)310 public static IResourceVariant asResourceVariant(IFileRevision revision) { 311 if (revision == null) 312 return null; 313 if (revision instanceof ResourceVariantFileRevision) { 314 ResourceVariantFileRevision rvfr = (ResourceVariantFileRevision) revision; 315 return rvfr.getVariant(); 316 } 317 if (revision instanceof IAdaptable) { 318 IAdaptable adaptable = (IAdaptable) revision; 319 Object o = adaptable.getAdapter(IResourceVariant.class); 320 if (o instanceof IResourceVariant) { 321 return (IResourceVariant) o; 322 } 323 } 324 return null; 325 } 326 getRemote(IDiff diff)327 public static IFileRevision getRemote(IDiff diff) { 328 if (diff instanceof IResourceDiff) { 329 IResourceDiff rd = (IResourceDiff) diff; 330 return rd.getAfterState(); 331 } 332 if (diff instanceof IThreeWayDiff) { 333 IThreeWayDiff twd = (IThreeWayDiff) diff; 334 return getRemote(twd); 335 } 336 return null; 337 } 338 getRemote(IThreeWayDiff twd)339 public static IFileRevision getRemote(IThreeWayDiff twd) { 340 IResourceDiff rd = (IResourceDiff)twd.getRemoteChange(); 341 if (rd != null) 342 return rd.getAfterState(); 343 rd = (IResourceDiff)twd.getLocalChange(); 344 if (rd != null) 345 return rd.getBeforeState(); 346 return null; 347 } 348 getDefault()349 public static SyncInfoToDiffConverter getDefault() { 350 if (instance == null) 351 instance = new SyncInfoToDiffConverter(); 352 return instance; 353 } 354 } 355